Merge "Report tests using Draw*BaseVertex as NotSupported" am: f96636fdfa am: eaf6e29...
[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         if (m_method == deqp::gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_BASEVERTEX ||
222                 m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED_BASEVERTEX ||
223                 m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED_BASEVERTEX)
224         {
225                 TCU_CHECK_AND_THROW(NotSupportedError, contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)), "This test requires a 3.2 context or higher context version.");
226         }
227
228         m_testCtx.getLog()      << TestLog::Message
229                                                 << "gl_VertexID should be the index of the vertex that is being passed to the shader. i.e. indices[i] + basevertex"
230                                                 << TestLog::EndMessage;
231
232         DE_ASSERT(!m_program);
233         m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(
234                 "#version 310 es\n"
235                 "in highp vec4 a_position;\n"
236                 "out mediump vec4 v_color;\n"
237                 "uniform highp vec4 u_colors[8];\n"
238                 "void main (void)\n"
239                 "{\n"
240                 "       gl_Position = a_position;\n"
241                 "       v_color = u_colors[gl_VertexID];\n"
242                 "}\n",
243
244                 "#version 310 es\n"
245                 "in mediump vec4 v_color;\n"
246                 "layout(location = 0) out mediump vec4 o_color;\n"
247                 "void main (void)\n"
248                 "{\n"
249                 "       o_color = v_color;\n"
250                 "}\n"));
251
252         m_testCtx.getLog() << *m_program;
253
254         if (!m_program->isOk())
255         {
256                 delete m_program;
257                 m_program = DE_NULL;
258                 TCU_FAIL("Failed to compile shader program");
259         }
260
261         GLU_CHECK_GLW_CALL(m_gl, useProgram(m_program->getProgram()));
262
263         GLU_CHECK_GLW_CALL(m_gl, genBuffers(1, &m_coordinatesBuffer));
264         GLU_CHECK_GLW_CALL(m_gl, genBuffers(1, &m_elementsBuffer));
265 }
266
267 void VertexIDCase::deinit (void)
268 {
269         delete m_program;
270         m_program = DE_NULL;
271
272         if (m_elementsBuffer)
273         {
274                 GLU_CHECK_GLW_CALL(m_gl, deleteBuffers(1, &m_elementsBuffer));
275                 m_elementsBuffer = 0;
276         }
277
278         if (m_coordinatesBuffer)
279         {
280                 GLU_CHECK_GLW_CALL(m_gl, deleteBuffers(1, &m_coordinatesBuffer));
281                 m_coordinatesBuffer = 0;
282         }
283 }
284
285 void VertexIDCase::draw (GLenum mode, GLsizei count, GLenum type, GLvoid* indices, GLint baseVertex)
286 {
287         switch (m_method)
288         {
289                 case gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_BASEVERTEX:
290                         GLU_CHECK_GLW_CALL(m_gl, drawElementsBaseVertex(mode, count, type, indices, baseVertex));
291                         break;
292
293                 case gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED_BASEVERTEX:
294                 {
295                         GLint maxElementsVertices = 0;
296                         GLU_CHECK_GLW_CALL(m_gl, getIntegerv(GL_MAX_ELEMENTS_VERTICES, &maxElementsVertices));
297                         GLU_CHECK_GLW_CALL(m_gl, drawRangeElementsBaseVertex(mode, 0, maxElementsVertices, count, type, indices, baseVertex));
298                         break;
299                 }
300
301                 case gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED_BASEVERTEX:
302                                 GLU_CHECK_GLW_CALL(m_gl, drawElementsInstancedBaseVertex(mode, count, type, indices, 1, baseVertex));
303                                 break;
304
305                 default:
306                         DE_FATAL("Draw method not supported");
307         }
308 }
309
310 void VertexIDCase::verifyImage (const tcu::Surface& image)
311 {
312         tcu::TestLog&   log                             = m_testCtx.getLog();
313         bool                    isOk                    = true;
314
315         const int               colorThreshold  = 0; // expect perfect match
316         tcu::Surface    error                   (image.getWidth(), image.getHeight());
317
318         for (int y = 0; y < image.getHeight(); y++)
319         for (int x = 0; x < image.getWidth(); x++)
320         {
321                 const tcu::RGBA pixel = image.getPixel(x, y);
322                 bool pixelOk = true;
323
324                 // Ignore pixels not drawn with basevertex
325                 if ((x < image.getWidth()* 1/4) || (x > image.getWidth()  * 3/4)
326                         || (y < image.getHeight() * 1/4) || (y > image.getHeight() * 3/4))
327                         continue;
328
329                 // Any pixel with !(B ~= 255) is faulty
330                 if (de::abs(pixel.getBlue() - 255) > colorThreshold)
331                         pixelOk = false;
332
333                 error.setPixel(x, y, (pixelOk) ? (tcu::RGBA(0, 255, 0, 255)) : (tcu::RGBA(255, 0, 0, 255)));
334                 isOk = isOk && pixelOk;
335         }
336
337         if (!isOk)
338         {
339                 log << TestLog::Message << "Image verification failed." << TestLog::EndMessage;
340                 log << TestLog::ImageSet("Verification result", "Result of rendering")
341                         << TestLog::Image("Result",             "Result",               image)
342                         << TestLog::Image("Error Mask", "Error mask",   error)
343                         << TestLog::EndImageSet;
344         }
345         else
346         {
347                 log << TestLog::ImageSet("Verification result", "Result of rendering")
348                         << TestLog::Image("Result", "Result", image)
349                         << TestLog::EndImageSet;
350         }
351
352         if (isOk)
353                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
354         else
355                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Result image invalid");
356 }
357
358 VertexIDCase::IterateResult VertexIDCase::iterate (void)
359 {
360         const GLuint                    drawCount                       = 6;
361         const GLuint                    baseVertex                      = 4;
362         const GLuint                    coordLocation           = m_gl.getAttribLocation(m_program->getProgram(), "a_position");
363         const GLuint                    colorLocation           = m_gl.getUniformLocation(m_program->getProgram(), "u_colors[0]");
364
365         tcu::Surface                    surface(VIEWPORT_WIDTH, VIEWPORT_HEIGHT);
366
367         const GLfloat coords[] =
368         {
369                 // full viewport quad
370                 -1.0f, -1.0f,
371                 +1.0f, -1.0f,
372                 +1.0f, +1.0f,
373                 -1.0f, +1.0f,
374
375                 // half viewport quad centred
376                 -0.5f, -0.5f,
377                 +0.5f, -0.5f,
378                 +0.5f, +0.5f,
379                 -0.5f, +0.5f,
380         };
381
382         const GLushort indices[] =
383         {
384                 0, 1, 2, 2, 3, 0,
385         };
386
387         const GLfloat colors[] =
388         {
389                 0.0f, 0.0f, 0.0f, 1.0f,
390                 0.5f, 1.0f, 0.5f, 1.0f,
391                 0.0f, 0.5f, 1.0f, 1.0f,
392                 0.0f, 1.0f, 0.0f, 1.0f,
393
394                 0.0f, 0.0f, 1.0f, 1.0f, // blue
395                 0.0f, 0.0f, 1.0f, 1.0f, // blue
396                 0.0f, 0.0f, 1.0f, 1.0f, // blue
397                 0.0f, 0.0f, 1.0f, 1.0f, // blue
398         };
399
400         GLU_CHECK_GLW_CALL(m_gl, viewport(0, 0, VIEWPORT_WIDTH, VIEWPORT_HEIGHT));
401         GLU_CHECK_GLW_CALL(m_gl, clearColor(1.0f, 1.0f, 1.0f, 1.0f)); // white
402         GLU_CHECK_GLW_CALL(m_gl, clear(GL_COLOR_BUFFER_BIT));
403
404         GLU_CHECK_GLW_CALL(m_gl, uniform4fv(colorLocation, DE_LENGTH_OF_ARRAY(colors), &colors[0]));
405
406         GLU_CHECK_GLW_CALL(m_gl, bindBuffer(GL_ARRAY_BUFFER, m_coordinatesBuffer));
407         GLU_CHECK_GLW_CALL(m_gl, bufferData(GL_ARRAY_BUFFER, (GLsizeiptr)sizeof(coords), coords, GL_STATIC_DRAW));
408         GLU_CHECK_GLW_CALL(m_gl, enableVertexAttribArray(coordLocation));
409         GLU_CHECK_GLW_CALL(m_gl, vertexAttribPointer(coordLocation, 2, GL_FLOAT, GL_FALSE, 0, DE_NULL));
410
411         if (m_iterNdx == 0)
412         {
413                 tcu::ScopedLogSection   logSection      (m_testCtx.getLog(), "Iter0", "Indices in client-side array");
414                 draw(GL_TRIANGLES, drawCount, GL_UNSIGNED_SHORT, (GLvoid*)indices, baseVertex);
415         }
416
417         if (m_iterNdx == 1)
418         {
419                 tcu::ScopedLogSection   logSection      (m_testCtx.getLog(), "Iter1", "Indices in element array buffer");
420                 GLU_CHECK_GLW_CALL(m_gl, bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementsBuffer));
421                 GLU_CHECK_GLW_CALL(m_gl, bufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)sizeof(indices), &indices[0], GL_STATIC_DRAW));
422                 draw(GL_TRIANGLES, drawCount, GL_UNSIGNED_SHORT, DE_NULL, baseVertex);
423         }
424
425         glu::readPixels(m_context.getRenderContext(), 0, 0, surface.getAccess());
426         verifyImage(surface);
427
428         m_iterNdx += 1;
429
430         return (m_iterNdx < 2) ? CONTINUE : STOP;
431 }
432
433 class BuiltInVariableGroup : public TestCaseGroup
434 {
435 public:
436                                                                         BuiltInVariableGroup            (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
437                                                                         ~BuiltInVariableGroup           (void);
438
439         void                                                    init                                            (void);
440
441 private:
442         gls::DrawTestSpec::DrawMethod   m_method;
443 };
444
445 BuiltInVariableGroup::BuiltInVariableGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
446         : TestCaseGroup         (context, name, descr)
447         , m_method                      (drawMethod)
448 {
449 }
450
451 BuiltInVariableGroup::~BuiltInVariableGroup (void)
452 {
453 }
454
455 void BuiltInVariableGroup::init (void)
456 {
457         addChild(new VertexIDCase(m_context, m_method));
458 }
459
460 class IndexGroup : public TestCaseGroup
461 {
462 public:
463                                                                         IndexGroup              (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
464                                                                         ~IndexGroup             (void);
465
466         void                                                    init                    (void);
467
468 private:
469         gls::DrawTestSpec::DrawMethod   m_method;
470 };
471
472 IndexGroup::IndexGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
473         : TestCaseGroup         (context, name, descr)
474         , m_method                      (drawMethod)
475 {
476 }
477
478 IndexGroup::~IndexGroup (void)
479 {
480 }
481
482 void IndexGroup::init (void)
483 {
484         struct IndexTest
485         {
486                 gls::DrawTestSpec::IndexType    type;
487                 int                                                             offsets[3];
488         };
489
490         const IndexTest tests[] =
491         {
492                 { gls::DrawTestSpec::INDEXTYPE_BYTE,    { 0, 1, -1 } },
493                 { gls::DrawTestSpec::INDEXTYPE_SHORT,   { 0, 2, -1 } },
494                 { gls::DrawTestSpec::INDEXTYPE_INT,             { 0, 4, -1 } },
495         };
496
497         gls::DrawTestSpec spec;
498         genBasicSpec(spec, m_method);
499
500         spec.indexStorage = gls::DrawTestSpec::STORAGE_BUFFER;
501
502         for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(tests); ++testNdx)
503         {
504                 const IndexTest&        indexTest       = tests[testNdx];
505
506                 const std::string       name            = std::string("index_") + gls::DrawTestSpec::indexTypeToString(indexTest.type);
507                 const std::string       desc            = std::string("index ") + gls::DrawTestSpec::indexTypeToString(indexTest.type);
508                 gls::DrawTest*          test            = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), name.c_str(), desc.c_str());
509
510                 spec.indexType                  = indexTest.type;
511
512                 for (int iterationNdx = 0; iterationNdx < DE_LENGTH_OF_ARRAY(indexTest.offsets) && indexTest.offsets[iterationNdx] != -1; ++iterationNdx)
513                 {
514                         const std::string iterationDesc = std::string("first vertex ") + de::toString(indexTest.offsets[iterationNdx] / gls::DrawTestSpec::indexTypeSize(indexTest.type));
515                         spec.indexPointerOffset = indexTest.offsets[iterationNdx];
516                         test->addIteration(spec, iterationDesc.c_str());
517                 }
518
519                 addChild(test);
520         }
521 }
522
523 class BaseVertexGroup : public TestCaseGroup
524 {
525 public:
526                                                                         BaseVertexGroup         (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
527                                                                         ~BaseVertexGroup        (void);
528
529         void                                                    init                            (void);
530
531 private:
532         gls::DrawTestSpec::DrawMethod   m_method;
533 };
534
535 BaseVertexGroup::BaseVertexGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
536         : TestCaseGroup         (context, name, descr)
537         , m_method                      (drawMethod)
538 {
539 }
540
541 BaseVertexGroup::~BaseVertexGroup (void)
542 {
543 }
544
545 void BaseVertexGroup::init (void)
546 {
547         struct IndexTest
548         {
549                 bool                                                    positiveBase;
550                 gls::DrawTestSpec::IndexType    type;
551                 int                                                             baseVertex[2];
552         };
553
554         const IndexTest tests[] =
555         {
556                 { true,  gls::DrawTestSpec::INDEXTYPE_BYTE,             {  1,  2 } },
557                 { true,  gls::DrawTestSpec::INDEXTYPE_SHORT,    {  1,  2 } },
558                 { true,  gls::DrawTestSpec::INDEXTYPE_INT,              {  1,  2 } },
559                 { false, gls::DrawTestSpec::INDEXTYPE_BYTE,             { -1, -2 } },
560                 { false, gls::DrawTestSpec::INDEXTYPE_SHORT,    { -1, -2 } },
561                 { false, gls::DrawTestSpec::INDEXTYPE_INT,              { -1, -2 } },
562         };
563
564         gls::DrawTestSpec spec;
565         genBasicSpec(spec, m_method);
566
567         spec.indexStorage = gls::DrawTestSpec::STORAGE_BUFFER;
568
569         for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(tests); ++testNdx)
570         {
571                 const IndexTest&        indexTest       = tests[testNdx];
572
573                 const std::string       name            = std::string("index_") + (indexTest.positiveBase ? "" : "neg_") + gls::DrawTestSpec::indexTypeToString(indexTest.type);
574                 const std::string       desc            = std::string("index ") + gls::DrawTestSpec::indexTypeToString(indexTest.type);
575                 gls::DrawTest*          test            = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), name.c_str(), desc.c_str());
576
577                 spec.indexType                  = indexTest.type;
578
579                 for (int iterationNdx = 0; iterationNdx < DE_LENGTH_OF_ARRAY(indexTest.baseVertex); ++iterationNdx)
580                 {
581                         const std::string iterationDesc = std::string("base vertex ") + de::toString(indexTest.baseVertex[iterationNdx]);
582                         spec.baseVertex = indexTest.baseVertex[iterationNdx];
583                         // spec.indexMin + spec.baseVertex can not be a negative value
584                         if (spec.indexMin + spec.baseVertex < 0)
585                         {
586                                 spec.indexMax -= (spec.indexMin + spec.baseVertex);
587                                 spec.indexMin -= (spec.indexMin + spec.baseVertex);
588                         }
589                         test->addIteration(spec, iterationDesc.c_str());
590                 }
591
592                 addChild(test);
593         }
594 }
595
596 class AttributeGroup : public TestCaseGroup
597 {
598 public:
599                                                                         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);
600                                                                         ~AttributeGroup (void);
601
602         void                                                    init                    (void);
603
604 private:
605         gls::DrawTestSpec::DrawMethod   m_method;
606         gls::DrawTestSpec::Primitive    m_primitive;
607         gls::DrawTestSpec::IndexType    m_indexType;
608         gls::DrawTestSpec::Storage              m_indexStorage;
609 };
610
611 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)
612         : TestCaseGroup         (context, name, descr)
613         , m_method                      (drawMethod)
614         , m_primitive           (primitive)
615         , m_indexType           (indexType)
616         , m_indexStorage        (indexStorage)
617 {
618 }
619
620 AttributeGroup::~AttributeGroup (void)
621 {
622 }
623
624 void AttributeGroup::init (void)
625 {
626         // Single attribute
627         {
628                 gls::DrawTest*          test                            = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "single_attribute", "Single attribute array.");
629                 gls::DrawTestSpec       spec;
630
631                 spec.apiType                                                    = glu::ApiType::es(3,1);
632                 spec.primitive                                                  = m_primitive;
633                 spec.primitiveCount                                             = 5;
634                 spec.drawMethod                                                 = m_method;
635                 spec.indexType                                                  = m_indexType;
636                 spec.indexPointerOffset                                 = 0;
637                 spec.indexStorage                                               = m_indexStorage;
638                 spec.first                                                              = 0;
639                 spec.indexMin                                                   = 0;
640                 spec.indexMax                                                   = 0;
641                 spec.instanceCount                                              = 1;
642                 spec.indirectOffset                                             = 0;
643
644                 spec.attribs.resize(1);
645
646                 spec.attribs[0].inputType                               = gls::DrawTestSpec::INPUTTYPE_FLOAT;
647                 spec.attribs[0].outputType                              = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
648                 spec.attribs[0].storage                                 = gls::DrawTestSpec::STORAGE_BUFFER;
649                 spec.attribs[0].usage                                   = gls::DrawTestSpec::USAGE_STATIC_DRAW;
650                 spec.attribs[0].componentCount                  = 2;
651                 spec.attribs[0].offset                                  = 0;
652                 spec.attribs[0].stride                                  = 0;
653                 spec.attribs[0].normalize                               = false;
654                 spec.attribs[0].instanceDivisor                 = 0;
655                 spec.attribs[0].useDefaultAttribute             = false;
656
657                 addTestIterations(test, spec, TYPE_DRAW_COUNT);
658
659                 this->addChild(test);
660         }
661
662         // Multiple attribute
663         {
664                 gls::DrawTest*          test                            = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "multiple_attributes", "Multiple attribute arrays.");
665                 gls::DrawTestSpec       spec;
666
667                 spec.apiType                                                    = glu::ApiType::es(3,1);
668                 spec.primitive                                                  = m_primitive;
669                 spec.primitiveCount                                             = 5;
670                 spec.drawMethod                                                 = m_method;
671                 spec.indexType                                                  = m_indexType;
672                 spec.indexPointerOffset                                 = 0;
673                 spec.indexStorage                                               = m_indexStorage;
674                 spec.first                                                              = 0;
675                 spec.indexMin                                                   = 0;
676                 spec.indexMax                                                   = 0;
677                 spec.instanceCount                                              = 1;
678                 spec.indirectOffset                                             = 0;
679
680                 spec.attribs.resize(2);
681
682                 spec.attribs[0].inputType                               = gls::DrawTestSpec::INPUTTYPE_FLOAT;
683                 spec.attribs[0].outputType                              = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
684                 spec.attribs[0].storage                                 = gls::DrawTestSpec::STORAGE_BUFFER;
685                 spec.attribs[0].usage                                   = gls::DrawTestSpec::USAGE_STATIC_DRAW;
686                 spec.attribs[0].componentCount                  = 4;
687                 spec.attribs[0].offset                                  = 0;
688                 spec.attribs[0].stride                                  = 0;
689                 spec.attribs[0].normalize                               = false;
690                 spec.attribs[0].instanceDivisor                 = 0;
691                 spec.attribs[0].useDefaultAttribute             = false;
692
693                 spec.attribs[1].inputType                               = gls::DrawTestSpec::INPUTTYPE_FLOAT;
694                 spec.attribs[1].outputType                              = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
695                 spec.attribs[1].storage                                 = gls::DrawTestSpec::STORAGE_BUFFER;
696                 spec.attribs[1].usage                                   = gls::DrawTestSpec::USAGE_STATIC_DRAW;
697                 spec.attribs[1].componentCount                  = 2;
698                 spec.attribs[1].offset                                  = 0;
699                 spec.attribs[1].stride                                  = 0;
700                 spec.attribs[1].normalize                               = false;
701                 spec.attribs[1].instanceDivisor                 = 0;
702                 spec.attribs[1].useDefaultAttribute             = false;
703
704                 addTestIterations(test, spec, TYPE_DRAW_COUNT);
705
706                 this->addChild(test);
707         }
708
709         // Multiple attribute, second one divided
710         {
711                 gls::DrawTest*          test                                    = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "instanced_attributes", "Instanced attribute array.");
712                 gls::DrawTestSpec       spec;
713
714                 spec.apiType                                                            = glu::ApiType::es(3,1);
715                 spec.primitive                                                          = m_primitive;
716                 spec.primitiveCount                                                     = 5;
717                 spec.drawMethod                                                         = m_method;
718                 spec.indexType                                                          = m_indexType;
719                 spec.indexPointerOffset                                         = 0;
720                 spec.indexStorage                                                       = m_indexStorage;
721                 spec.first                                                                      = 0;
722                 spec.indexMin                                                           = 0;
723                 spec.indexMax                                                           = 0;
724                 spec.instanceCount                                                      = 1;
725                 spec.indirectOffset                                                     = 0;
726
727                 spec.attribs.resize(3);
728
729                 spec.attribs[0].inputType                                       = gls::DrawTestSpec::INPUTTYPE_FLOAT;
730                 spec.attribs[0].outputType                                      = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
731                 spec.attribs[0].storage                                         = gls::DrawTestSpec::STORAGE_BUFFER;
732                 spec.attribs[0].usage                                           = gls::DrawTestSpec::USAGE_STATIC_DRAW;
733                 spec.attribs[0].componentCount                          = 4;
734                 spec.attribs[0].offset                                          = 0;
735                 spec.attribs[0].stride                                          = 0;
736                 spec.attribs[0].normalize                                       = false;
737                 spec.attribs[0].instanceDivisor                         = 0;
738                 spec.attribs[0].useDefaultAttribute                     = false;
739
740                 // Add another position component so the instances wont be drawn on each other
741                 spec.attribs[1].inputType                                       = gls::DrawTestSpec::INPUTTYPE_FLOAT;
742                 spec.attribs[1].outputType                                      = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
743                 spec.attribs[1].storage                                         = gls::DrawTestSpec::STORAGE_BUFFER;
744                 spec.attribs[1].usage                                           = gls::DrawTestSpec::USAGE_STATIC_DRAW;
745                 spec.attribs[1].componentCount                          = 2;
746                 spec.attribs[1].offset                                          = 0;
747                 spec.attribs[1].stride                                          = 0;
748                 spec.attribs[1].normalize                                       = false;
749                 spec.attribs[1].instanceDivisor                         = 1;
750                 spec.attribs[1].useDefaultAttribute                     = false;
751                 spec.attribs[1].additionalPositionAttribute     = true;
752
753                 // Instanced color
754                 spec.attribs[2].inputType                                       = gls::DrawTestSpec::INPUTTYPE_FLOAT;
755                 spec.attribs[2].outputType                                      = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
756                 spec.attribs[2].storage                                         = gls::DrawTestSpec::STORAGE_BUFFER;
757                 spec.attribs[2].usage                                           = gls::DrawTestSpec::USAGE_STATIC_DRAW;
758                 spec.attribs[2].componentCount                          = 3;
759                 spec.attribs[2].offset                                          = 0;
760                 spec.attribs[2].stride                                          = 0;
761                 spec.attribs[2].normalize                                       = false;
762                 spec.attribs[2].instanceDivisor                         = 1;
763                 spec.attribs[2].useDefaultAttribute                     = false;
764
765                 addTestIterations(test, spec, TYPE_INSTANCE_COUNT);
766
767                 this->addChild(test);
768         }
769
770         // Multiple attribute, second one default
771         {
772                 gls::DrawTest*          test                            = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "default_attribute", "Attribute specified with glVertexAttrib*.");
773                 gls::DrawTestSpec       spec;
774
775                 spec.apiType                                                    = glu::ApiType::es(3,1);
776                 spec.primitive                                                  = m_primitive;
777                 spec.primitiveCount                                             = 5;
778                 spec.drawMethod                                                 = m_method;
779                 spec.indexType                                                  = m_indexType;
780                 spec.indexPointerOffset                                 = 0;
781                 spec.indexStorage                                               = m_indexStorage;
782                 spec.first                                                              = 0;
783                 spec.indexMin                                                   = 0;
784                 spec.indexMax                                                   = 0;
785                 spec.instanceCount                                              = 1;
786                 spec.indirectOffset                                             = 0;
787
788                 spec.attribs.resize(2);
789
790                 spec.attribs[0].inputType                               = gls::DrawTestSpec::INPUTTYPE_FLOAT;
791                 spec.attribs[0].outputType                              = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
792                 spec.attribs[0].storage                                 = gls::DrawTestSpec::STORAGE_BUFFER;
793                 spec.attribs[0].usage                                   = gls::DrawTestSpec::USAGE_STATIC_DRAW;
794                 spec.attribs[0].componentCount                  = 2;
795                 spec.attribs[0].offset                                  = 0;
796                 spec.attribs[0].stride                                  = 0;
797                 spec.attribs[0].normalize                               = false;
798                 spec.attribs[0].instanceDivisor                 = 0;
799                 spec.attribs[0].useDefaultAttribute             = false;
800
801                 struct IOPair
802                 {
803                         gls::DrawTestSpec::InputType  input;
804                         gls::DrawTestSpec::OutputType output;
805                         int                                                       componentCount;
806                 } iopairs[] =
807                 {
808                         { gls::DrawTestSpec::INPUTTYPE_FLOAT,            gls::DrawTestSpec::OUTPUTTYPE_VEC2,  4 },
809                         { gls::DrawTestSpec::INPUTTYPE_FLOAT,            gls::DrawTestSpec::OUTPUTTYPE_VEC4,  2 },
810                         { gls::DrawTestSpec::INPUTTYPE_INT,                      gls::DrawTestSpec::OUTPUTTYPE_IVEC3, 4 },
811                         { gls::DrawTestSpec::INPUTTYPE_UNSIGNED_INT, gls::DrawTestSpec::OUTPUTTYPE_UVEC2, 4 },
812                 };
813
814                 for (int ioNdx = 0; ioNdx < DE_LENGTH_OF_ARRAY(iopairs); ++ioNdx)
815                 {
816                         const std::string desc = gls::DrawTestSpec::inputTypeToString(iopairs[ioNdx].input) + de::toString(iopairs[ioNdx].componentCount) + " to " + gls::DrawTestSpec::outputTypeToString(iopairs[ioNdx].output);
817
818                         spec.attribs[1].inputType                       = iopairs[ioNdx].input;
819                         spec.attribs[1].outputType                      = iopairs[ioNdx].output;
820                         spec.attribs[1].storage                         = gls::DrawTestSpec::STORAGE_BUFFER;
821                         spec.attribs[1].usage                           = gls::DrawTestSpec::USAGE_STATIC_DRAW;
822                         spec.attribs[1].componentCount          = iopairs[ioNdx].componentCount;
823                         spec.attribs[1].offset                          = 0;
824                         spec.attribs[1].stride                          = 0;
825                         spec.attribs[1].normalize                       = false;
826                         spec.attribs[1].instanceDivisor         = 0;
827                         spec.attribs[1].useDefaultAttribute     = true;
828
829                         test->addIteration(spec, desc.c_str());
830                 }
831
832                 this->addChild(test);
833         }
834 }
835
836 class MethodGroup : public TestCaseGroup
837 {
838 public:
839                                                                         MethodGroup                     (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
840                                                                         ~MethodGroup            (void);
841
842         void                                                    init                            (void);
843
844 private:
845         gls::DrawTestSpec::DrawMethod   m_method;
846 };
847
848 MethodGroup::MethodGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
849         : TestCaseGroup         (context, name, descr)
850         , m_method                      (drawMethod)
851 {
852 }
853
854 MethodGroup::~MethodGroup (void)
855 {
856 }
857
858 void MethodGroup::init (void)
859 {
860         const bool indexed              =       (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_BASEVERTEX)
861                                                         ||      (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED_BASEVERTEX)
862                                                         ||      (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED_BASEVERTEX);
863
864         const gls::DrawTestSpec::Primitive primitive[] =
865         {
866                 gls::DrawTestSpec::PRIMITIVE_POINTS,
867                 gls::DrawTestSpec::PRIMITIVE_TRIANGLES,
868                 gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN,
869                 gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP,
870                 gls::DrawTestSpec::PRIMITIVE_LINES,
871                 gls::DrawTestSpec::PRIMITIVE_LINE_STRIP,
872                 gls::DrawTestSpec::PRIMITIVE_LINE_LOOP
873         };
874
875         if (indexed)
876         {
877                 // Index-tests
878                 this->addChild(new IndexGroup(m_context, "indices", "Index tests", m_method));
879                 this->addChild(new BaseVertexGroup(m_context, "base_vertex", "Base vertex tests", m_method));
880                 this->addChild(new BuiltInVariableGroup(m_context, "builtin_variable", "Built in shader variable tests", m_method));
881         }
882
883         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(primitive); ++ndx)
884         {
885                 const std::string name = gls::DrawTestSpec::primitiveToString(primitive[ndx]);
886                 const std::string desc = gls::DrawTestSpec::primitiveToString(primitive[ndx]);
887
888                 this->addChild(new AttributeGroup(m_context, name.c_str(), desc.c_str(), m_method, primitive[ndx], gls::DrawTestSpec::INDEXTYPE_SHORT, gls::DrawTestSpec::STORAGE_BUFFER));
889         }
890 }
891
892 } // anonymous
893
894 DrawElementsBaseVertexTests::DrawElementsBaseVertexTests (Context& context)
895         : TestCaseGroup(context, "draw_base_vertex", "Base vertex extension drawing tests")
896 {
897 }
898
899 DrawElementsBaseVertexTests::~DrawElementsBaseVertexTests (void)
900 {
901 }
902
903 void DrawElementsBaseVertexTests::init (void)
904 {
905         const gls::DrawTestSpec::DrawMethod basicMethods[] =
906         {
907                 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_BASEVERTEX,
908                 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED_BASEVERTEX,
909                 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INSTANCED_BASEVERTEX,
910         };
911
912         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(basicMethods); ++ndx)
913         {
914                 const std::string name = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]);
915                 const std::string desc = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]);
916
917                 this->addChild(new MethodGroup(m_context, name.c_str(), desc.c_str(), basicMethods[ndx]));
918         }
919 }
920
921 } // Functional
922 } // gles31
923 } // deqp