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