Add new draw elements base vertex tests
[platform/upstream/VK-GL-CTS.git] / modules / gles31 / functional / es31fDrawElementsBaseVertexTests.cpp
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 3.1 Module
3  * -------------------------------------------------
4  *
5  * Copyright 2017 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 GL_EXT_draw_elements_base_vertex tests.
22  *//*--------------------------------------------------------------------*/
23
24 #include "es31fDrawElementsBaseVertexTests.hpp"
25 #include "deRandom.hpp"
26 #include "deStringUtil.hpp"
27 #include "tcuRenderTarget.hpp"
28 #include "tcuVectorUtil.hpp"
29 #include "sglrGLContext.hpp"
30 #include "glsDrawTest.hpp"
31 #include "gluStrUtil.hpp"
32 #include "gluPixelTransfer.hpp"
33 #include "gluContextInfo.hpp"
34
35 #include "glwEnums.hpp"
36 #include "glwFunctions.hpp"
37
38 #include <string>
39 #include <set>
40
41 using std::vector;
42 using std::string;
43 using tcu::TestLog;
44
45 using namespace glw;
46
47 namespace deqp
48 {
49 namespace gles31
50 {
51 namespace Functional
52 {
53 namespace
54 {
55
56 enum TestIterationType
57 {
58         TYPE_DRAW_COUNT,                // !< test with 1, 5, and 25 primitives
59         TYPE_INSTANCE_COUNT,    // !< test with 1, 4, and 11 instances
60
61         TYPE_LAST
62 };
63
64 static size_t getElementCount (gls::DrawTestSpec::Primitive primitive, size_t primitiveCount)
65 {
66         switch (primitive)
67         {
68                 case gls::DrawTestSpec::PRIMITIVE_POINTS:                                               return primitiveCount;
69                 case gls::DrawTestSpec::PRIMITIVE_TRIANGLES:                                    return primitiveCount * 3;
70                 case gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN:                                 return primitiveCount + 2;
71                 case gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP:                               return primitiveCount + 2;
72                 case gls::DrawTestSpec::PRIMITIVE_LINES:                                                return primitiveCount * 2;
73                 case gls::DrawTestSpec::PRIMITIVE_LINE_STRIP:                                   return primitiveCount + 1;
74                 case gls::DrawTestSpec::PRIMITIVE_LINE_LOOP:                                    return (primitiveCount==1) ? (2) : (primitiveCount);
75                 case gls::DrawTestSpec::PRIMITIVE_LINES_ADJACENCY:                              return primitiveCount * 4;
76                 case gls::DrawTestSpec::PRIMITIVE_LINE_STRIP_ADJACENCY:                 return primitiveCount + 3;
77                 case gls::DrawTestSpec::PRIMITIVE_TRIANGLES_ADJACENCY:                  return primitiveCount * 6;
78                 case gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP_ADJACENCY:             return primitiveCount * 2 + 4;
79                 default:
80                         DE_ASSERT(false);
81                         return 0;
82         }
83 }
84
85 static void addRangeElementsToSpec (gls::DrawTestSpec& spec)
86 {
87         if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED_BASEVERTEX)
88         {
89                 spec.indexMin = 0;
90                 spec.indexMax = (int)getElementCount(spec.primitive, spec.primitiveCount);
91         }
92 }
93
94 static void addTestIterations (gls::DrawTest* test, gls::DrawTestSpec& spec, TestIterationType type)
95 {
96         if (type == TYPE_DRAW_COUNT)
97         {
98                 spec.primitiveCount = 1;
99                 addRangeElementsToSpec(spec);
100                 test->addIteration(spec, "draw count = 1");
101
102                 spec.primitiveCount = 5;
103                 addRangeElementsToSpec(spec);
104                 test->addIteration(spec, "draw count = 5");
105
106                 spec.primitiveCount = 25;
107                 addRangeElementsToSpec(spec);
108                 test->addIteration(spec, "draw count = 25");
109         }
110         else if (type == TYPE_INSTANCE_COUNT)
111         {
112                 spec.instanceCount = 1;
113                 addRangeElementsToSpec(spec);
114                 test->addIteration(spec, "instance count = 1");
115
116                 spec.instanceCount = 4;
117                 addRangeElementsToSpec(spec);
118                 test->addIteration(spec, "instance count = 4");
119
120                 spec.instanceCount = 11;
121                 addRangeElementsToSpec(spec);
122                 test->addIteration(spec, "instance count = 11");
123         }
124         else
125                 DE_ASSERT(false);
126 }
127
128 static void genBasicSpec (gls::DrawTestSpec& spec, gls::DrawTestSpec::DrawMethod method)
129 {
130         spec.apiType                                                    = glu::ApiType::es(3,1);
131         spec.primitive                                                  = gls::DrawTestSpec::PRIMITIVE_TRIANGLES;
132         spec.primitiveCount                                             = 5;
133         spec.drawMethod                                                 = method;
134         spec.indexType                                                  = gls::DrawTestSpec::INDEXTYPE_LAST;
135         spec.indexPointerOffset                                 = 0;
136         spec.indexStorage                                               = gls::DrawTestSpec::STORAGE_LAST;
137         spec.first                                                              = 0;
138         spec.indexMin                                                   = 0;
139         spec.indexMax                                                   = 0;
140         spec.instanceCount                                              = 1;
141         spec.indirectOffset                                             = 0;
142
143         spec.attribs.resize(2);
144
145         spec.attribs[0].inputType                               = gls::DrawTestSpec::INPUTTYPE_FLOAT;
146         spec.attribs[0].outputType                              = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
147         spec.attribs[0].storage                                 = gls::DrawTestSpec::STORAGE_BUFFER;
148         spec.attribs[0].usage                                   = gls::DrawTestSpec::USAGE_STATIC_DRAW;
149         spec.attribs[0].componentCount                  = 4;
150         spec.attribs[0].offset                                  = 0;
151         spec.attribs[0].stride                                  = 0;
152         spec.attribs[0].normalize                               = false;
153         spec.attribs[0].instanceDivisor                 = 0;
154         spec.attribs[0].useDefaultAttribute             = false;
155
156         spec.attribs[1].inputType                               = gls::DrawTestSpec::INPUTTYPE_FLOAT;
157         spec.attribs[1].outputType                              = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
158         spec.attribs[1].storage                                 = gls::DrawTestSpec::STORAGE_BUFFER;
159         spec.attribs[1].usage                                   = gls::DrawTestSpec::USAGE_STATIC_DRAW;
160         spec.attribs[1].componentCount                  = 2;
161         spec.attribs[1].offset                                  = 0;
162         spec.attribs[1].stride                                  = 0;
163         spec.attribs[1].normalize                               = false;
164         spec.attribs[1].instanceDivisor                 = 0;
165         spec.attribs[1].useDefaultAttribute             = false;
166
167         addRangeElementsToSpec(spec);
168 }
169
170 class VertexIDCase : public TestCase
171 {
172 public:
173                                                                         VertexIDCase                    (Context& context, gls::DrawTestSpec::DrawMethod drawMethod);
174                                                                         ~VertexIDCase                   (void);
175
176         void                                                    init                                    (void);
177         void                                                    deinit                                  (void);
178         IterateResult                                   iterate                                 (void);
179
180         void                                                    draw                                    (GLenum mode, GLsizei count, GLenum type, GLvoid* indices, GLint baseVertex);
181         void                                                    verifyImage                             (const tcu::Surface& image);
182
183 private:
184         const glw::Functions&                   m_gl;
185         glu::ShaderProgram*                             m_program;
186         GLuint                                                  m_coordinatesBuffer;
187         GLuint                                                  m_elementsBuffer;
188         int                                                             m_iterNdx;
189         gls::DrawTestSpec::DrawMethod   m_method;
190
191         enum
192         {
193                 VIEWPORT_WIDTH = 64,
194                 VIEWPORT_HEIGHT = 64
195         };
196
197         enum
198         {
199                 MAX_VERTICES = 2*3      //!< 2 triangles, totals 6 vertices
200         };
201 };
202
203 VertexIDCase::VertexIDCase (Context& context,  gls::DrawTestSpec::DrawMethod drawMethod)
204         : TestCase                              (context, "vertex_id", "gl_VertexID Test")
205         , m_gl                                  (m_context.getRenderContext().getFunctions())
206         , m_program                             (DE_NULL)
207         , m_coordinatesBuffer   (0)
208         , m_elementsBuffer              (0)
209         , m_iterNdx                             (0)
210         , m_method                              (drawMethod)
211 {
212 }
213
214 VertexIDCase::~VertexIDCase (void)
215 {
216         VertexIDCase::deinit();
217 }
218
219 void VertexIDCase::init (void)
220 {
221         m_testCtx.getLog()      << TestLog::Message
222                                                 << "gl_VertexID should be the index of the vertex that is being passed to the shader. i.e. indices[i] + basevertex"
223                                                 << TestLog::EndMessage;
224
225         DE_ASSERT(!m_program);
226         m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(
227                 "#version 310 es\n"
228                 "in highp vec4 a_position;\n"
229                 "out mediump vec4 v_color;\n"
230                 "uniform highp vec4 u_colors[8];\n"
231                 "void main (void)\n"
232                 "{\n"
233                 "       gl_Position = a_position;\n"
234                 "       v_color = u_colors[gl_VertexID];\n"
235                 "}\n",
236
237                 "#version 310 es\n"
238                 "in mediump vec4 v_color;\n"
239                 "layout(location = 0) out mediump vec4 o_color;\n"
240                 "void main (void)\n"
241                 "{\n"
242                 "       o_color = v_color;\n"
243                 "}\n"));
244
245         m_testCtx.getLog() << *m_program;
246
247         if (!m_program->isOk())
248         {
249                 delete m_program;
250                 m_program = DE_NULL;
251                 TCU_FAIL("Failed to compile shader program");
252         }
253
254         GLU_CHECK_GLW_CALL(m_gl, useProgram(m_program->getProgram()));
255
256         GLU_CHECK_GLW_CALL(m_gl, genBuffers(1, &m_coordinatesBuffer));
257         GLU_CHECK_GLW_CALL(m_gl, genBuffers(1, &m_elementsBuffer));
258 }
259
260 void VertexIDCase::deinit (void)
261 {
262         delete m_program;
263         m_program = DE_NULL;
264
265         if (m_elementsBuffer)
266         {
267                 GLU_CHECK_GLW_CALL(m_gl, deleteBuffers(1, &m_elementsBuffer));
268                 m_elementsBuffer = 0;
269         }
270
271         if (m_coordinatesBuffer)
272         {
273                 GLU_CHECK_GLW_CALL(m_gl, deleteBuffers(1, &m_coordinatesBuffer));
274                 m_coordinatesBuffer = 0;
275         }
276 }
277
278 void VertexIDCase::draw (GLenum mode, GLsizei count, GLenum type, GLvoid* indices, GLint baseVertex)
279 {
280         switch (m_method)
281         {
282                 case gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_BASEVERTEX:
283                         GLU_CHECK_GLW_CALL(m_gl, drawElementsBaseVertex(mode, count, type, indices, baseVertex));
284                         break;
285
286                 case gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED_BASEVERTEX:
287                 {
288                         GLint maxElementsVertices = 0;
289                         GLU_CHECK_GLW_CALL(m_gl, getIntegerv(GL_MAX_ELEMENTS_VERTICES, &maxElementsVertices));
290                         GLU_CHECK_GLW_CALL(m_gl, drawRangeElementsBaseVertex(mode, 0, maxElementsVertices, count, type, indices, baseVertex));
291                         break;
292                 }
293
294                 case gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED_BASEVERTEX:
295                                 GLU_CHECK_GLW_CALL(m_gl, drawElementsInstancedBaseVertex(mode, count, type, indices, 1, baseVertex));
296                                 break;
297
298                 default:
299                         DE_FATAL("Draw method not supported");
300         }
301 }
302
303 void VertexIDCase::verifyImage (const tcu::Surface& image)
304 {
305         tcu::TestLog&   log                             = m_testCtx.getLog();
306         bool                    isOk                    = true;
307
308         const int               colorThreshold  = 0; // expect perfect match
309         tcu::Surface    error                   (image.getWidth(), image.getHeight());
310
311         for (int y = 0; y < image.getHeight(); y++)
312         for (int x = 0; x < image.getWidth(); x++)
313         {
314                 const tcu::RGBA pixel = image.getPixel(x, y);
315                 bool pixelOk = true;
316
317                 // Ignore pixels not drawn with basevertex
318                 if ((x < image.getWidth()* 1/4) || (x > image.getWidth()  * 3/4)
319                         || (y < image.getHeight() * 1/4) || (y > image.getHeight() * 3/4))
320                         continue;
321
322                 // Any pixel with !(B ~= 255) is faulty
323                 if (de::abs(pixel.getBlue() - 255) > colorThreshold)
324                         pixelOk = false;
325
326                 error.setPixel(x, y, (pixelOk) ? (tcu::RGBA(0, 255, 0, 255)) : (tcu::RGBA(255, 0, 0, 255)));
327                 isOk = isOk && pixelOk;
328         }
329
330         if (!isOk)
331         {
332                 log << TestLog::Message << "Image verification failed." << TestLog::EndMessage;
333                 log << TestLog::ImageSet("Verification result", "Result of rendering")
334                         << TestLog::Image("Result",             "Result",               image)
335                         << TestLog::Image("Error Mask", "Error mask",   error)
336                         << TestLog::EndImageSet;
337         }
338         else
339         {
340                 log << TestLog::ImageSet("Verification result", "Result of rendering")
341                         << TestLog::Image("Result", "Result", image)
342                         << TestLog::EndImageSet;
343         }
344
345         if (isOk)
346                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
347         else
348                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Result image invalid");
349 }
350
351 VertexIDCase::IterateResult VertexIDCase::iterate (void)
352 {
353         const GLuint                    drawCount                       = 6;
354         const GLuint                    baseVertex                      = 4;
355         const GLuint                    coordLocation           = m_gl.getAttribLocation(m_program->getProgram(), "a_position");
356         const GLuint                    colorLocation           = m_gl.getUniformLocation(m_program->getProgram(), "u_colors[0]");
357
358         tcu::Surface                    surface(VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
359
360         const GLfloat coords[] =
361         {
362                 // full viewport quad
363                 -1.0f, -1.0f,
364                 +1.0f, -1.0f,
365                 +1.0f, +1.0f,
366                 -1.0f, +1.0f,
367
368                 // half viewport quad centred
369                 -0.5f, -0.5f,
370                 +0.5f, -0.5f,
371                 +0.5f, +0.5f,
372                 -0.5f, +0.5f,
373         };
374
375         const GLushort indices[] =
376         {
377                 0, 1, 2, 2, 3, 0,
378         };
379
380         const GLfloat colors[] =
381         {
382                 0.0f, 0.0f, 0.0f, 1.0f,
383                 0.5f, 1.0f, 0.5f, 1.0f,
384                 0.0f, 0.5f, 1.0f, 1.0f,
385                 0.0f, 1.0f, 0.0f, 1.0f,
386
387                 0.0f, 0.0f, 1.0f, 1.0f, // blue
388                 0.0f, 0.0f, 1.0f, 1.0f, // blue
389                 0.0f, 0.0f, 1.0f, 1.0f, // blue
390                 0.0f, 0.0f, 1.0f, 1.0f, // blue
391         };
392
393         GLU_CHECK_GLW_CALL(m_gl, viewport(0, 0, VIEWPORT_WIDTH, VIEWPORT_HEIGHT));
394         GLU_CHECK_GLW_CALL(m_gl, clearColor(1.0f, 1.0f, 1.0f, 1.0f)); // white
395         GLU_CHECK_GLW_CALL(m_gl, clear(GL_COLOR_BUFFER_BIT));
396
397         GLU_CHECK_GLW_CALL(m_gl, uniform4fv(colorLocation, DE_LENGTH_OF_ARRAY(colors), &colors[0]));
398
399         GLU_CHECK_GLW_CALL(m_gl, bindBuffer(GL_ARRAY_BUFFER, m_coordinatesBuffer));
400         GLU_CHECK_GLW_CALL(m_gl, bufferData(GL_ARRAY_BUFFER, (GLsizeiptr)sizeof(coords), coords, GL_STATIC_DRAW));
401         GLU_CHECK_GLW_CALL(m_gl, enableVertexAttribArray(coordLocation));
402         GLU_CHECK_GLW_CALL(m_gl, vertexAttribPointer(coordLocation, 2, GL_FLOAT, GL_FALSE, 0, DE_NULL));
403
404         if (m_iterNdx == 0)
405         {
406                 tcu::ScopedLogSection   logSection      (m_testCtx.getLog(), "Iter0", "Indices in client-side array");
407                 draw(GL_TRIANGLES, drawCount, GL_UNSIGNED_SHORT, (GLvoid*)indices, baseVertex);
408         }
409
410         if (m_iterNdx == 1)
411         {
412                 tcu::ScopedLogSection   logSection      (m_testCtx.getLog(), "Iter1", "Indices in element array buffer");
413                 GLU_CHECK_GLW_CALL(m_gl, bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementsBuffer));
414                 GLU_CHECK_GLW_CALL(m_gl, bufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)sizeof(indices), &indices[0], GL_STATIC_DRAW));
415                 draw(GL_TRIANGLES, drawCount, GL_UNSIGNED_SHORT, DE_NULL, baseVertex);
416         }
417
418         glu::readPixels(m_context.getRenderContext(), 0, 0, surface.getAccess());
419         verifyImage(surface);
420
421         m_iterNdx += 1;
422
423         return (m_iterNdx < 2) ? CONTINUE : STOP;
424 }
425
426 class BuiltInVariableGroup : public TestCaseGroup
427 {
428 public:
429                                                                         BuiltInVariableGroup            (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
430                                                                         ~BuiltInVariableGroup           (void);
431
432         void                                                    init                                            (void);
433
434 private:
435         gls::DrawTestSpec::DrawMethod   m_method;
436 };
437
438 BuiltInVariableGroup::BuiltInVariableGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
439         : TestCaseGroup         (context, name, descr)
440         , m_method                      (drawMethod)
441 {
442 }
443
444 BuiltInVariableGroup::~BuiltInVariableGroup (void)
445 {
446 }
447
448 void BuiltInVariableGroup::init (void)
449 {
450         addChild(new VertexIDCase(m_context, m_method));
451 }
452
453 class IndexGroup : public TestCaseGroup
454 {
455 public:
456                                                                         IndexGroup              (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
457                                                                         ~IndexGroup             (void);
458
459         void                                                    init                    (void);
460
461 private:
462         gls::DrawTestSpec::DrawMethod   m_method;
463 };
464
465 IndexGroup::IndexGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
466         : TestCaseGroup         (context, name, descr)
467         , m_method                      (drawMethod)
468 {
469 }
470
471 IndexGroup::~IndexGroup (void)
472 {
473 }
474
475 void IndexGroup::init (void)
476 {
477         struct IndexTest
478         {
479                 gls::DrawTestSpec::IndexType    type;
480                 int                                                             offsets[3];
481         };
482
483         const IndexTest tests[] =
484         {
485                 { gls::DrawTestSpec::INDEXTYPE_BYTE,    { 0, 1, -1 } },
486                 { gls::DrawTestSpec::INDEXTYPE_SHORT,   { 0, 2, -1 } },
487                 { gls::DrawTestSpec::INDEXTYPE_INT,             { 0, 4, -1 } },
488         };
489
490         gls::DrawTestSpec spec;
491         genBasicSpec(spec, m_method);
492
493         spec.indexStorage = gls::DrawTestSpec::STORAGE_BUFFER;
494
495         for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(tests); ++testNdx)
496         {
497                 const IndexTest&        indexTest       = tests[testNdx];
498
499                 const std::string       name            = std::string("index_") + gls::DrawTestSpec::indexTypeToString(indexTest.type);
500                 const std::string       desc            = std::string("index ") + gls::DrawTestSpec::indexTypeToString(indexTest.type);
501                 gls::DrawTest*          test            = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), name.c_str(), desc.c_str());
502
503                 spec.indexType                  = indexTest.type;
504
505                 for (int iterationNdx = 0; iterationNdx < DE_LENGTH_OF_ARRAY(indexTest.offsets) && indexTest.offsets[iterationNdx] != -1; ++iterationNdx)
506                 {
507                         const std::string iterationDesc = std::string("first vertex ") + de::toString(indexTest.offsets[iterationNdx] / gls::DrawTestSpec::indexTypeSize(indexTest.type));
508                         spec.indexPointerOffset = indexTest.offsets[iterationNdx];
509                         test->addIteration(spec, iterationDesc.c_str());
510                 }
511
512                 addChild(test);
513         }
514 }
515
516 class BaseVertexGroup : public TestCaseGroup
517 {
518 public:
519                                                                         BaseVertexGroup         (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
520                                                                         ~BaseVertexGroup        (void);
521
522         void                                                    init                            (void);
523
524 private:
525         gls::DrawTestSpec::DrawMethod   m_method;
526 };
527
528 BaseVertexGroup::BaseVertexGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
529         : TestCaseGroup         (context, name, descr)
530         , m_method                      (drawMethod)
531 {
532 }
533
534 BaseVertexGroup::~BaseVertexGroup (void)
535 {
536 }
537
538 void BaseVertexGroup::init (void)
539 {
540         struct IndexTest
541         {
542                 bool                                                    positiveBase;
543                 gls::DrawTestSpec::IndexType    type;
544                 int                                                             baseVertex[2];
545         };
546
547         const IndexTest tests[] =
548         {
549                 { true,  gls::DrawTestSpec::INDEXTYPE_BYTE,             {  1,  2 } },
550                 { true,  gls::DrawTestSpec::INDEXTYPE_SHORT,    {  1,  2 } },
551                 { true,  gls::DrawTestSpec::INDEXTYPE_INT,              {  1,  2 } },
552                 { false, gls::DrawTestSpec::INDEXTYPE_BYTE,             { -1, -2 } },
553                 { false, gls::DrawTestSpec::INDEXTYPE_SHORT,    { -1, -2 } },
554                 { false, gls::DrawTestSpec::INDEXTYPE_INT,              { -1, -2 } },
555         };
556
557         gls::DrawTestSpec spec;
558         genBasicSpec(spec, m_method);
559
560         spec.indexStorage = gls::DrawTestSpec::STORAGE_BUFFER;
561
562         for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(tests); ++testNdx)
563         {
564                 const IndexTest&        indexTest       = tests[testNdx];
565
566                 const std::string       name            = std::string("index_") + (indexTest.positiveBase ? "" : "neg_") + gls::DrawTestSpec::indexTypeToString(indexTest.type);
567                 const std::string       desc            = std::string("index ") + gls::DrawTestSpec::indexTypeToString(indexTest.type);
568                 gls::DrawTest*          test            = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), name.c_str(), desc.c_str());
569
570                 spec.indexType                  = indexTest.type;
571
572                 for (int iterationNdx = 0; iterationNdx < DE_LENGTH_OF_ARRAY(indexTest.baseVertex); ++iterationNdx)
573                 {
574                         const std::string iterationDesc = std::string("base vertex ") + de::toString(indexTest.baseVertex[iterationNdx]);
575                         spec.baseVertex = indexTest.baseVertex[iterationNdx];
576                         test->addIteration(spec, iterationDesc.c_str());
577                 }
578
579                 addChild(test);
580         }
581 }
582
583 class AttributeGroup : public TestCaseGroup
584 {
585 public:
586                                                                         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);
587                                                                         ~AttributeGroup (void);
588
589         void                                                    init                    (void);
590
591 private:
592         gls::DrawTestSpec::DrawMethod   m_method;
593         gls::DrawTestSpec::Primitive    m_primitive;
594         gls::DrawTestSpec::IndexType    m_indexType;
595         gls::DrawTestSpec::Storage              m_indexStorage;
596 };
597
598 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)
599         : TestCaseGroup         (context, name, descr)
600         , m_method                      (drawMethod)
601         , m_primitive           (primitive)
602         , m_indexType           (indexType)
603         , m_indexStorage        (indexStorage)
604 {
605 }
606
607 AttributeGroup::~AttributeGroup (void)
608 {
609 }
610
611 void AttributeGroup::init (void)
612 {
613         // Single attribute
614         {
615                 gls::DrawTest*          test                            = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "single_attribute", "Single attribute array.");
616                 gls::DrawTestSpec       spec;
617
618                 spec.apiType                                                    = glu::ApiType::es(3,1);
619                 spec.primitive                                                  = m_primitive;
620                 spec.primitiveCount                                             = 5;
621                 spec.drawMethod                                                 = m_method;
622                 spec.indexType                                                  = m_indexType;
623                 spec.indexPointerOffset                                 = 0;
624                 spec.indexStorage                                               = m_indexStorage;
625                 spec.first                                                              = 0;
626                 spec.indexMin                                                   = 0;
627                 spec.indexMax                                                   = 0;
628                 spec.instanceCount                                              = 1;
629                 spec.indirectOffset                                             = 0;
630
631                 spec.attribs.resize(1);
632
633                 spec.attribs[0].inputType                               = gls::DrawTestSpec::INPUTTYPE_FLOAT;
634                 spec.attribs[0].outputType                              = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
635                 spec.attribs[0].storage                                 = gls::DrawTestSpec::STORAGE_BUFFER;
636                 spec.attribs[0].usage                                   = gls::DrawTestSpec::USAGE_STATIC_DRAW;
637                 spec.attribs[0].componentCount                  = 2;
638                 spec.attribs[0].offset                                  = 0;
639                 spec.attribs[0].stride                                  = 0;
640                 spec.attribs[0].normalize                               = false;
641                 spec.attribs[0].instanceDivisor                 = 0;
642                 spec.attribs[0].useDefaultAttribute             = false;
643
644                 addTestIterations(test, spec, TYPE_DRAW_COUNT);
645
646                 this->addChild(test);
647         }
648
649         // Multiple attribute
650         {
651                 gls::DrawTest*          test                            = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "multiple_attributes", "Multiple attribute arrays.");
652                 gls::DrawTestSpec       spec;
653
654                 spec.apiType                                                    = glu::ApiType::es(3,1);
655                 spec.primitive                                                  = m_primitive;
656                 spec.primitiveCount                                             = 5;
657                 spec.drawMethod                                                 = m_method;
658                 spec.indexType                                                  = m_indexType;
659                 spec.indexPointerOffset                                 = 0;
660                 spec.indexStorage                                               = m_indexStorage;
661                 spec.first                                                              = 0;
662                 spec.indexMin                                                   = 0;
663                 spec.indexMax                                                   = 0;
664                 spec.instanceCount                                              = 1;
665                 spec.indirectOffset                                             = 0;
666
667                 spec.attribs.resize(2);
668
669                 spec.attribs[0].inputType                               = gls::DrawTestSpec::INPUTTYPE_FLOAT;
670                 spec.attribs[0].outputType                              = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
671                 spec.attribs[0].storage                                 = gls::DrawTestSpec::STORAGE_BUFFER;
672                 spec.attribs[0].usage                                   = gls::DrawTestSpec::USAGE_STATIC_DRAW;
673                 spec.attribs[0].componentCount                  = 4;
674                 spec.attribs[0].offset                                  = 0;
675                 spec.attribs[0].stride                                  = 0;
676                 spec.attribs[0].normalize                               = false;
677                 spec.attribs[0].instanceDivisor                 = 0;
678                 spec.attribs[0].useDefaultAttribute             = false;
679
680                 spec.attribs[1].inputType                               = gls::DrawTestSpec::INPUTTYPE_FLOAT;
681                 spec.attribs[1].outputType                              = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
682                 spec.attribs[1].storage                                 = gls::DrawTestSpec::STORAGE_BUFFER;
683                 spec.attribs[1].usage                                   = gls::DrawTestSpec::USAGE_STATIC_DRAW;
684                 spec.attribs[1].componentCount                  = 2;
685                 spec.attribs[1].offset                                  = 0;
686                 spec.attribs[1].stride                                  = 0;
687                 spec.attribs[1].normalize                               = false;
688                 spec.attribs[1].instanceDivisor                 = 0;
689                 spec.attribs[1].useDefaultAttribute             = false;
690
691                 addTestIterations(test, spec, TYPE_DRAW_COUNT);
692
693                 this->addChild(test);
694         }
695
696         // Multiple attribute, second one divided
697         {
698                 gls::DrawTest*          test                                    = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "instanced_attributes", "Instanced attribute array.");
699                 gls::DrawTestSpec       spec;
700
701                 spec.apiType                                                            = glu::ApiType::es(3,1);
702                 spec.primitive                                                          = m_primitive;
703                 spec.primitiveCount                                                     = 5;
704                 spec.drawMethod                                                         = m_method;
705                 spec.indexType                                                          = m_indexType;
706                 spec.indexPointerOffset                                         = 0;
707                 spec.indexStorage                                                       = m_indexStorage;
708                 spec.first                                                                      = 0;
709                 spec.indexMin                                                           = 0;
710                 spec.indexMax                                                           = 0;
711                 spec.instanceCount                                                      = 1;
712                 spec.indirectOffset                                                     = 0;
713
714                 spec.attribs.resize(3);
715
716                 spec.attribs[0].inputType                                       = gls::DrawTestSpec::INPUTTYPE_FLOAT;
717                 spec.attribs[0].outputType                                      = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
718                 spec.attribs[0].storage                                         = gls::DrawTestSpec::STORAGE_BUFFER;
719                 spec.attribs[0].usage                                           = gls::DrawTestSpec::USAGE_STATIC_DRAW;
720                 spec.attribs[0].componentCount                          = 4;
721                 spec.attribs[0].offset                                          = 0;
722                 spec.attribs[0].stride                                          = 0;
723                 spec.attribs[0].normalize                                       = false;
724                 spec.attribs[0].instanceDivisor                         = 0;
725                 spec.attribs[0].useDefaultAttribute                     = false;
726
727                 // Add another position component so the instances wont be drawn on each other
728                 spec.attribs[1].inputType                                       = gls::DrawTestSpec::INPUTTYPE_FLOAT;
729                 spec.attribs[1].outputType                                      = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
730                 spec.attribs[1].storage                                         = gls::DrawTestSpec::STORAGE_BUFFER;
731                 spec.attribs[1].usage                                           = gls::DrawTestSpec::USAGE_STATIC_DRAW;
732                 spec.attribs[1].componentCount                          = 2;
733                 spec.attribs[1].offset                                          = 0;
734                 spec.attribs[1].stride                                          = 0;
735                 spec.attribs[1].normalize                                       = false;
736                 spec.attribs[1].instanceDivisor                         = 1;
737                 spec.attribs[1].useDefaultAttribute                     = false;
738                 spec.attribs[1].additionalPositionAttribute     = true;
739
740                 // Instanced color
741                 spec.attribs[2].inputType                                       = gls::DrawTestSpec::INPUTTYPE_FLOAT;
742                 spec.attribs[2].outputType                                      = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
743                 spec.attribs[2].storage                                         = gls::DrawTestSpec::STORAGE_BUFFER;
744                 spec.attribs[2].usage                                           = gls::DrawTestSpec::USAGE_STATIC_DRAW;
745                 spec.attribs[2].componentCount                          = 3;
746                 spec.attribs[2].offset                                          = 0;
747                 spec.attribs[2].stride                                          = 0;
748                 spec.attribs[2].normalize                                       = false;
749                 spec.attribs[2].instanceDivisor                         = 1;
750                 spec.attribs[2].useDefaultAttribute                     = false;
751
752                 addTestIterations(test, spec, TYPE_INSTANCE_COUNT);
753
754                 this->addChild(test);
755         }
756
757         // Multiple attribute, second one default
758         {
759                 gls::DrawTest*          test                            = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "default_attribute", "Attribute specified with glVertexAttrib*.");
760                 gls::DrawTestSpec       spec;
761
762                 spec.apiType                                                    = glu::ApiType::es(3,1);
763                 spec.primitive                                                  = m_primitive;
764                 spec.primitiveCount                                             = 5;
765                 spec.drawMethod                                                 = m_method;
766                 spec.indexType                                                  = m_indexType;
767                 spec.indexPointerOffset                                 = 0;
768                 spec.indexStorage                                               = m_indexStorage;
769                 spec.first                                                              = 0;
770                 spec.indexMin                                                   = 0;
771                 spec.indexMax                                                   = 0;
772                 spec.instanceCount                                              = 1;
773                 spec.indirectOffset                                             = 0;
774
775                 spec.attribs.resize(2);
776
777                 spec.attribs[0].inputType                               = gls::DrawTestSpec::INPUTTYPE_FLOAT;
778                 spec.attribs[0].outputType                              = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
779                 spec.attribs[0].storage                                 = gls::DrawTestSpec::STORAGE_BUFFER;
780                 spec.attribs[0].usage                                   = gls::DrawTestSpec::USAGE_STATIC_DRAW;
781                 spec.attribs[0].componentCount                  = 2;
782                 spec.attribs[0].offset                                  = 0;
783                 spec.attribs[0].stride                                  = 0;
784                 spec.attribs[0].normalize                               = false;
785                 spec.attribs[0].instanceDivisor                 = 0;
786                 spec.attribs[0].useDefaultAttribute             = false;
787
788                 struct IOPair
789                 {
790                         gls::DrawTestSpec::InputType  input;
791                         gls::DrawTestSpec::OutputType output;
792                         int                                                       componentCount;
793                 } iopairs[] =
794                 {
795                         { gls::DrawTestSpec::INPUTTYPE_FLOAT,            gls::DrawTestSpec::OUTPUTTYPE_VEC2,  4 },
796                         { gls::DrawTestSpec::INPUTTYPE_FLOAT,            gls::DrawTestSpec::OUTPUTTYPE_VEC4,  2 },
797                         { gls::DrawTestSpec::INPUTTYPE_INT,                      gls::DrawTestSpec::OUTPUTTYPE_IVEC3, 4 },
798                         { gls::DrawTestSpec::INPUTTYPE_UNSIGNED_INT, gls::DrawTestSpec::OUTPUTTYPE_UVEC2, 4 },
799                 };
800
801                 for (int ioNdx = 0; ioNdx < DE_LENGTH_OF_ARRAY(iopairs); ++ioNdx)
802                 {
803                         const std::string desc = gls::DrawTestSpec::inputTypeToString(iopairs[ioNdx].input) + de::toString(iopairs[ioNdx].componentCount) + " to " + gls::DrawTestSpec::outputTypeToString(iopairs[ioNdx].output);
804
805                         spec.attribs[1].inputType                       = iopairs[ioNdx].input;
806                         spec.attribs[1].outputType                      = iopairs[ioNdx].output;
807                         spec.attribs[1].storage                         = gls::DrawTestSpec::STORAGE_BUFFER;
808                         spec.attribs[1].usage                           = gls::DrawTestSpec::USAGE_STATIC_DRAW;
809                         spec.attribs[1].componentCount          = iopairs[ioNdx].componentCount;
810                         spec.attribs[1].offset                          = 0;
811                         spec.attribs[1].stride                          = 0;
812                         spec.attribs[1].normalize                       = false;
813                         spec.attribs[1].instanceDivisor         = 0;
814                         spec.attribs[1].useDefaultAttribute     = true;
815
816                         test->addIteration(spec, desc.c_str());
817                 }
818
819                 this->addChild(test);
820         }
821 }
822
823 class MethodGroup : public TestCaseGroup
824 {
825 public:
826                                                                         MethodGroup                     (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
827                                                                         ~MethodGroup            (void);
828
829         void                                                    init                            (void);
830
831 private:
832         gls::DrawTestSpec::DrawMethod   m_method;
833 };
834
835 MethodGroup::MethodGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
836         : TestCaseGroup         (context, name, descr)
837         , m_method                      (drawMethod)
838 {
839 }
840
841 MethodGroup::~MethodGroup (void)
842 {
843 }
844
845 void MethodGroup::init (void)
846 {
847         const bool indexed              =       (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_BASEVERTEX)
848                                                         ||      (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED_BASEVERTEX)
849                                                         ||      (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED_BASEVERTEX);
850
851         const gls::DrawTestSpec::Primitive primitive[] =
852         {
853                 gls::DrawTestSpec::PRIMITIVE_POINTS,
854                 gls::DrawTestSpec::PRIMITIVE_TRIANGLES,
855                 gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN,
856                 gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP,
857                 gls::DrawTestSpec::PRIMITIVE_LINES,
858                 gls::DrawTestSpec::PRIMITIVE_LINE_STRIP,
859                 gls::DrawTestSpec::PRIMITIVE_LINE_LOOP
860         };
861
862         if (indexed)
863         {
864                 // Index-tests
865                 this->addChild(new IndexGroup(m_context, "indices", "Index tests", m_method));
866                 this->addChild(new BaseVertexGroup(m_context, "base_vertex", "Base vertex tests", m_method));
867                 this->addChild(new BuiltInVariableGroup(m_context, "builtin_variable", "Built in shader variable tests", m_method));
868         }
869
870         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(primitive); ++ndx)
871         {
872                 const std::string name = gls::DrawTestSpec::primitiveToString(primitive[ndx]);
873                 const std::string desc = gls::DrawTestSpec::primitiveToString(primitive[ndx]);
874
875                 this->addChild(new AttributeGroup(m_context, name.c_str(), desc.c_str(), m_method, primitive[ndx], gls::DrawTestSpec::INDEXTYPE_SHORT, gls::DrawTestSpec::STORAGE_BUFFER));
876         }
877 }
878
879 } // anonymous
880
881 DrawElementsBaseVertexTests::DrawElementsBaseVertexTests (Context& context)
882         : TestCaseGroup(context, "draw_base_vertex", "Base vertex extension drawing tests")
883 {
884 }
885
886 DrawElementsBaseVertexTests::~DrawElementsBaseVertexTests (void)
887 {
888 }
889
890 void DrawElementsBaseVertexTests::init (void)
891 {
892         const gls::DrawTestSpec::DrawMethod basicMethods[] =
893         {
894                 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_BASEVERTEX,
895                 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED_BASEVERTEX,
896                 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED_BASEVERTEX,
897         };
898
899         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(basicMethods); ++ndx)
900         {
901                 const std::string name = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]);
902                 const std::string desc = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]);
903
904                 this->addChild(new MethodGroup(m_context, name.c_str(), desc.c_str(), basicMethods[ndx]));
905         }
906 }
907
908 } // Functional
909 } // gles31
910 } // deqp