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