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