Fix PIPELINE_STAGE_TOP_OF_PIPE_BIT usage in api tests
[platform/upstream/VK-GL-CTS.git] / modules / gles31 / functional / es31fDrawTests.cpp
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 3.1 Module
3  * -------------------------------------------------
4  *
5  * Copyright 2014 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 Drawing tests.
22  *//*--------------------------------------------------------------------*/
23
24 #include "es31fDrawTests.hpp"
25 #include "deRandom.hpp"
26 #include "deStringUtil.hpp"
27 #include "deMemory.h"
28 #include "tcuRenderTarget.hpp"
29 #include "tcuVectorUtil.hpp"
30 #include "sglrGLContext.hpp"
31 #include "glsDrawTest.hpp"
32 #include "gluStrUtil.hpp"
33 #include "gluPixelTransfer.hpp"
34 #include "gluCallLogWrapper.hpp"
35
36 #include "glwEnums.hpp"
37 #include "glwFunctions.hpp"
38
39 #include <set>
40
41 namespace deqp
42 {
43 namespace gles31
44 {
45 namespace Functional
46 {
47 namespace
48 {
49
50 enum TestIterationType
51 {
52         TYPE_DRAW_COUNT,                // !< test with 1, 5, and 25 primitives
53         TYPE_INSTANCE_COUNT,    // !< test with 1, 4, and 11 instances
54
55         TYPE_LAST
56 };
57
58 static const char* s_commonVertexShaderSource =         "#version 310 es\n"
59                                                                                                         "in highp vec4 a_position;\n"
60                                                                                                         "void main (void)\n"
61                                                                                                         "{\n"
62                                                                                                         "       gl_Position = a_position;\n"
63                                                                                                         "}\n";
64 static const char* s_commonFragmentShaderSource =       "#version 310 es\n"
65                                                                                                         "layout(location = 0) out highp vec4 fragColor;\n"
66                                                                                                         "void main (void)\n"
67                                                                                                         "{\n"
68                                                                                                         "       fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
69                                                                                                         "}\n";
70
71 static const char* s_colorVertexShaderSource =          "#version 310 es\n"
72                                                                                                         "in highp vec4 a_position;\n"
73                                                                                                         "in highp vec4 a_color;\n"
74                                                                                                         "out highp vec4 v_color;\n"
75                                                                                                         "void main (void)\n"
76                                                                                                         "{\n"
77                                                                                                         "       gl_Position = a_position;\n"
78                                                                                                         "       v_color = a_color;\n"
79                                                                                                         "}\n";
80 static const char* s_colorFragmentShaderSource  =       "#version 310 es\n"
81                                                                                                         "layout(location = 0) out highp vec4 fragColor;\n"
82                                                                                                         "in highp vec4 v_color;\n"
83                                                                                                         "void main (void)\n"
84                                                                                                         "{\n"
85                                                                                                         "       fragColor = v_color;\n"
86                                                                                                         "}\n";
87 struct DrawElementsCommand
88 {
89         deUint32 count;
90         deUint32 primCount;
91         deUint32 firstIndex;
92         deInt32  baseVertex;
93         deUint32 reservedMustBeZero;
94 };
95 DE_STATIC_ASSERT(5 * sizeof(deUint32) == sizeof(DrawElementsCommand)); // tight packing
96
97 struct DrawArraysCommand
98 {
99         deUint32 count;
100         deUint32 primCount;
101         deUint32 first;
102         deUint32 reservedMustBeZero;
103 };
104 DE_STATIC_ASSERT(4 * sizeof(deUint32) == sizeof(DrawArraysCommand)); // tight packing
105
106 // Verifies image contains only yellow or greeen, or a linear combination
107 // of these colors.
108 static bool verifyImageYellowGreen (const tcu::Surface& image, tcu::TestLog& log)
109 {
110         using tcu::TestLog;
111
112         const int colorThreshold        = 20;
113
114         tcu::Surface error                      (image.getWidth(), image.getHeight());
115         bool isOk                                       = true;
116
117         for (int y = 0; y < image.getHeight(); y++)
118         for (int x = 0; x < image.getWidth(); x++)
119         {
120                 const tcu::RGBA pixel = image.getPixel(x, y);
121                 bool pixelOk = true;
122
123                 // Any pixel with !(G ~= 255) is faulty (not a linear combinations of green and yellow)
124                 if (de::abs(pixel.getGreen() - 255) > colorThreshold)
125                         pixelOk = false;
126
127                 // Any pixel with !(B ~= 0) is faulty (not a linear combinations of green and yellow)
128                 if (de::abs(pixel.getBlue() - 0) > colorThreshold)
129                         pixelOk = false;
130
131                 error.setPixel(x, y, (pixelOk) ? (tcu::RGBA(0, 255, 0, 255)) : (tcu::RGBA(255, 0, 0, 255)));
132                 isOk = isOk && pixelOk;
133         }
134
135         if (!isOk)
136         {
137                 log << TestLog::Message << "Image verification failed." << TestLog::EndMessage;
138                 log << TestLog::ImageSet("Verfication result", "Result of rendering")
139                         << TestLog::Image("Result",             "Result",               image)
140                         << TestLog::Image("ErrorMask",  "Error mask",   error)
141                         << TestLog::EndImageSet;
142         }
143         else
144         {
145                 log << TestLog::ImageSet("Verfication result", "Result of rendering")
146                         << TestLog::Image("Result", "Result", image)
147                         << TestLog::EndImageSet;
148         }
149
150         return isOk;
151 }
152
153 static void addTestIterations (gls::DrawTest* test, gls::DrawTestSpec& spec, TestIterationType type)
154 {
155         if (type == TYPE_DRAW_COUNT)
156         {
157                 spec.primitiveCount = 1;
158                 test->addIteration(spec, "draw count = 1");
159
160                 spec.primitiveCount = 5;
161                 test->addIteration(spec, "draw count = 5");
162
163                 spec.primitiveCount = 25;
164                 test->addIteration(spec, "draw count = 25");
165         }
166         else if (type == TYPE_INSTANCE_COUNT)
167         {
168                 spec.instanceCount = 1;
169                 test->addIteration(spec, "instance count = 1");
170
171                 spec.instanceCount = 4;
172                 test->addIteration(spec, "instance count = 4");
173
174                 spec.instanceCount = 11;
175                 test->addIteration(spec, "instance count = 11");
176         }
177         else
178                 DE_ASSERT(false);
179 }
180
181 static void genBasicSpec (gls::DrawTestSpec& spec, gls::DrawTestSpec::DrawMethod method)
182 {
183         spec.apiType                                                    = glu::ApiType::es(3,1);
184         spec.primitive                                                  = gls::DrawTestSpec::PRIMITIVE_TRIANGLES;
185         spec.primitiveCount                                             = 5;
186         spec.drawMethod                                                 = method;
187         spec.indexType                                                  = gls::DrawTestSpec::INDEXTYPE_LAST;
188         spec.indexPointerOffset                                 = 0;
189         spec.indexStorage                                               = gls::DrawTestSpec::STORAGE_LAST;
190         spec.first                                                              = 0;
191         spec.indexMin                                                   = 0;
192         spec.indexMax                                                   = 0;
193         spec.instanceCount                                              = 1;
194         spec.indirectOffset                                             = 0;
195
196         spec.attribs.resize(2);
197
198         spec.attribs[0].inputType                               = gls::DrawTestSpec::INPUTTYPE_FLOAT;
199         spec.attribs[0].outputType                              = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
200         spec.attribs[0].storage                                 = gls::DrawTestSpec::STORAGE_BUFFER;
201         spec.attribs[0].usage                                   = gls::DrawTestSpec::USAGE_STATIC_DRAW;
202         spec.attribs[0].componentCount                  = 4;
203         spec.attribs[0].offset                                  = 0;
204         spec.attribs[0].stride                                  = 0;
205         spec.attribs[0].normalize                               = false;
206         spec.attribs[0].instanceDivisor                 = 0;
207         spec.attribs[0].useDefaultAttribute             = false;
208
209         spec.attribs[1].inputType                               = gls::DrawTestSpec::INPUTTYPE_FLOAT;
210         spec.attribs[1].outputType                              = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
211         spec.attribs[1].storage                                 = gls::DrawTestSpec::STORAGE_BUFFER;
212         spec.attribs[1].usage                                   = gls::DrawTestSpec::USAGE_STATIC_DRAW;
213         spec.attribs[1].componentCount                  = 2;
214         spec.attribs[1].offset                                  = 0;
215         spec.attribs[1].stride                                  = 0;
216         spec.attribs[1].normalize                               = false;
217         spec.attribs[1].instanceDivisor                 = 0;
218         spec.attribs[1].useDefaultAttribute             = false;
219 }
220
221 static std::string sizeToString (int size)
222 {
223         if (size < 1024)
224                 return de::toString(size) + " byte(s)";
225         if (size < 1024*1024)
226                 return de::toString(size / 1024) + " KB";
227         return de::toString(size / 1024 / 1024) + " MB";
228 }
229
230 class AttributeGroup : public TestCaseGroup
231 {
232 public:
233                                                                         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);
234                                                                         ~AttributeGroup (void);
235
236         void                                                    init                    (void);
237
238 private:
239         gls::DrawTestSpec::DrawMethod   m_method;
240         gls::DrawTestSpec::Primitive    m_primitive;
241         gls::DrawTestSpec::IndexType    m_indexType;
242         gls::DrawTestSpec::Storage              m_indexStorage;
243 };
244
245 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)
246         : TestCaseGroup         (context, name, descr)
247         , m_method                      (drawMethod)
248         , m_primitive           (primitive)
249         , m_indexType           (indexType)
250         , m_indexStorage        (indexStorage)
251 {
252 }
253
254 AttributeGroup::~AttributeGroup (void)
255 {
256 }
257
258 void AttributeGroup::init (void)
259 {
260         // Single attribute
261         {
262                 gls::DrawTest*          test                            = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "single_attribute", "Single attribute array.");
263                 gls::DrawTestSpec       spec;
264
265                 spec.apiType                                                    = glu::ApiType::es(3,1);
266                 spec.primitive                                                  = m_primitive;
267                 spec.primitiveCount                                             = 5;
268                 spec.drawMethod                                                 = m_method;
269                 spec.indexType                                                  = m_indexType;
270                 spec.indexPointerOffset                                 = 0;
271                 spec.indexStorage                                               = m_indexStorage;
272                 spec.first                                                              = 0;
273                 spec.indexMin                                                   = 0;
274                 spec.indexMax                                                   = 0;
275                 spec.instanceCount                                              = 1;
276                 spec.indirectOffset                                             = 0;
277
278                 spec.attribs.resize(1);
279
280                 spec.attribs[0].inputType                               = gls::DrawTestSpec::INPUTTYPE_FLOAT;
281                 spec.attribs[0].outputType                              = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
282                 spec.attribs[0].storage                                 = gls::DrawTestSpec::STORAGE_BUFFER;
283                 spec.attribs[0].usage                                   = gls::DrawTestSpec::USAGE_STATIC_DRAW;
284                 spec.attribs[0].componentCount                  = 2;
285                 spec.attribs[0].offset                                  = 0;
286                 spec.attribs[0].stride                                  = 0;
287                 spec.attribs[0].normalize                               = false;
288                 spec.attribs[0].instanceDivisor                 = 0;
289                 spec.attribs[0].useDefaultAttribute             = false;
290
291                 addTestIterations(test, spec, TYPE_DRAW_COUNT);
292
293                 this->addChild(test);
294         }
295
296         // Multiple attribute
297         {
298                 gls::DrawTest*          test                            = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "multiple_attributes", "Multiple attribute arrays.");
299                 gls::DrawTestSpec       spec;
300
301                 spec.apiType                                                    = glu::ApiType::es(3,1);
302                 spec.primitive                                                  = m_primitive;
303                 spec.primitiveCount                                             = 5;
304                 spec.drawMethod                                                 = m_method;
305                 spec.indexType                                                  = m_indexType;
306                 spec.indexPointerOffset                                 = 0;
307                 spec.indexStorage                                               = m_indexStorage;
308                 spec.first                                                              = 0;
309                 spec.indexMin                                                   = 0;
310                 spec.indexMax                                                   = 0;
311                 spec.instanceCount                                              = 1;
312                 spec.indirectOffset                                             = 0;
313
314                 spec.attribs.resize(2);
315
316                 spec.attribs[0].inputType                               = gls::DrawTestSpec::INPUTTYPE_FLOAT;
317                 spec.attribs[0].outputType                              = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
318                 spec.attribs[0].storage                                 = gls::DrawTestSpec::STORAGE_BUFFER;
319                 spec.attribs[0].usage                                   = gls::DrawTestSpec::USAGE_STATIC_DRAW;
320                 spec.attribs[0].componentCount                  = 4;
321                 spec.attribs[0].offset                                  = 0;
322                 spec.attribs[0].stride                                  = 0;
323                 spec.attribs[0].normalize                               = false;
324                 spec.attribs[0].instanceDivisor                 = 0;
325                 spec.attribs[0].useDefaultAttribute             = false;
326
327                 spec.attribs[1].inputType                               = gls::DrawTestSpec::INPUTTYPE_FLOAT;
328                 spec.attribs[1].outputType                              = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
329                 spec.attribs[1].storage                                 = gls::DrawTestSpec::STORAGE_BUFFER;
330                 spec.attribs[1].usage                                   = gls::DrawTestSpec::USAGE_STATIC_DRAW;
331                 spec.attribs[1].componentCount                  = 2;
332                 spec.attribs[1].offset                                  = 0;
333                 spec.attribs[1].stride                                  = 0;
334                 spec.attribs[1].normalize                               = false;
335                 spec.attribs[1].instanceDivisor                 = 0;
336                 spec.attribs[1].useDefaultAttribute             = false;
337
338                 addTestIterations(test, spec, TYPE_DRAW_COUNT);
339
340                 this->addChild(test);
341         }
342
343         // Multiple attribute, second one divided
344         {
345                 gls::DrawTest*          test                                    = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "instanced_attributes", "Instanced attribute array.");
346                 gls::DrawTestSpec       spec;
347
348                 spec.apiType                                                            = glu::ApiType::es(3,1);
349                 spec.primitive                                                          = m_primitive;
350                 spec.primitiveCount                                                     = 5;
351                 spec.drawMethod                                                         = m_method;
352                 spec.indexType                                                          = m_indexType;
353                 spec.indexPointerOffset                                         = 0;
354                 spec.indexStorage                                                       = m_indexStorage;
355                 spec.first                                                                      = 0;
356                 spec.indexMin                                                           = 0;
357                 spec.indexMax                                                           = 0;
358                 spec.instanceCount                                                      = 1;
359                 spec.indirectOffset                                                     = 0;
360
361                 spec.attribs.resize(3);
362
363                 spec.attribs[0].inputType                                       = gls::DrawTestSpec::INPUTTYPE_FLOAT;
364                 spec.attribs[0].outputType                                      = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
365                 spec.attribs[0].storage                                         = gls::DrawTestSpec::STORAGE_BUFFER;
366                 spec.attribs[0].usage                                           = gls::DrawTestSpec::USAGE_STATIC_DRAW;
367                 spec.attribs[0].componentCount                          = 4;
368                 spec.attribs[0].offset                                          = 0;
369                 spec.attribs[0].stride                                          = 0;
370                 spec.attribs[0].normalize                                       = false;
371                 spec.attribs[0].instanceDivisor                         = 0;
372                 spec.attribs[0].useDefaultAttribute                     = false;
373
374                 // Add another position component so the instances wont be drawn on each other
375                 spec.attribs[1].inputType                                       = gls::DrawTestSpec::INPUTTYPE_FLOAT;
376                 spec.attribs[1].outputType                                      = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
377                 spec.attribs[1].storage                                         = gls::DrawTestSpec::STORAGE_BUFFER;
378                 spec.attribs[1].usage                                           = gls::DrawTestSpec::USAGE_STATIC_DRAW;
379                 spec.attribs[1].componentCount                          = 2;
380                 spec.attribs[1].offset                                          = 0;
381                 spec.attribs[1].stride                                          = 0;
382                 spec.attribs[1].normalize                                       = false;
383                 spec.attribs[1].instanceDivisor                         = 1;
384                 spec.attribs[1].useDefaultAttribute                     = false;
385                 spec.attribs[1].additionalPositionAttribute     = true;
386
387                 // Instanced color
388                 spec.attribs[2].inputType                                       = gls::DrawTestSpec::INPUTTYPE_FLOAT;
389                 spec.attribs[2].outputType                                      = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
390                 spec.attribs[2].storage                                         = gls::DrawTestSpec::STORAGE_BUFFER;
391                 spec.attribs[2].usage                                           = gls::DrawTestSpec::USAGE_STATIC_DRAW;
392                 spec.attribs[2].componentCount                          = 3;
393                 spec.attribs[2].offset                                          = 0;
394                 spec.attribs[2].stride                                          = 0;
395                 spec.attribs[2].normalize                                       = false;
396                 spec.attribs[2].instanceDivisor                         = 1;
397                 spec.attribs[2].useDefaultAttribute                     = false;
398
399                 addTestIterations(test, spec, TYPE_INSTANCE_COUNT);
400
401                 this->addChild(test);
402         }
403
404         // Multiple attribute, second one default
405         {
406                 gls::DrawTest*          test                            = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), "default_attribute", "Attribute specified with glVertexAttrib*.");
407                 gls::DrawTestSpec       spec;
408
409                 spec.apiType                                                    = glu::ApiType::es(3,1);
410                 spec.primitive                                                  = m_primitive;
411                 spec.primitiveCount                                             = 5;
412                 spec.drawMethod                                                 = m_method;
413                 spec.indexType                                                  = m_indexType;
414                 spec.indexPointerOffset                                 = 0;
415                 spec.indexStorage                                               = m_indexStorage;
416                 spec.first                                                              = 0;
417                 spec.indexMin                                                   = 0;
418                 spec.indexMax                                                   = 0;
419                 spec.instanceCount                                              = 1;
420                 spec.indirectOffset                                             = 0;
421
422                 spec.attribs.resize(2);
423
424                 spec.attribs[0].inputType                               = gls::DrawTestSpec::INPUTTYPE_FLOAT;
425                 spec.attribs[0].outputType                              = gls::DrawTestSpec::OUTPUTTYPE_VEC2;
426                 spec.attribs[0].storage                                 = gls::DrawTestSpec::STORAGE_BUFFER;
427                 spec.attribs[0].usage                                   = gls::DrawTestSpec::USAGE_STATIC_DRAW;
428                 spec.attribs[0].componentCount                  = 2;
429                 spec.attribs[0].offset                                  = 0;
430                 spec.attribs[0].stride                                  = 0;
431                 spec.attribs[0].normalize                               = false;
432                 spec.attribs[0].instanceDivisor                 = 0;
433                 spec.attribs[0].useDefaultAttribute             = false;
434
435                 struct IOPair
436                 {
437                         gls::DrawTestSpec::InputType  input;
438                         gls::DrawTestSpec::OutputType output;
439                         int                                                       componentCount;
440                 } iopairs[] =
441                 {
442                         { gls::DrawTestSpec::INPUTTYPE_FLOAT,        gls::DrawTestSpec::OUTPUTTYPE_VEC2,  4 },
443                         { gls::DrawTestSpec::INPUTTYPE_FLOAT,        gls::DrawTestSpec::OUTPUTTYPE_VEC4,  2 },
444                         { gls::DrawTestSpec::INPUTTYPE_INT,          gls::DrawTestSpec::OUTPUTTYPE_IVEC3, 4 },
445                         { gls::DrawTestSpec::INPUTTYPE_UNSIGNED_INT, gls::DrawTestSpec::OUTPUTTYPE_UVEC2, 4 },
446                 };
447
448                 for (int ioNdx = 0; ioNdx < DE_LENGTH_OF_ARRAY(iopairs); ++ioNdx)
449                 {
450                         const std::string desc = gls::DrawTestSpec::inputTypeToString(iopairs[ioNdx].input) + de::toString(iopairs[ioNdx].componentCount) + " to " + gls::DrawTestSpec::outputTypeToString(iopairs[ioNdx].output);
451
452                         spec.attribs[1].inputType                       = iopairs[ioNdx].input;
453                         spec.attribs[1].outputType                      = iopairs[ioNdx].output;
454                         spec.attribs[1].storage                         = gls::DrawTestSpec::STORAGE_BUFFER;
455                         spec.attribs[1].usage                           = gls::DrawTestSpec::USAGE_STATIC_DRAW;
456                         spec.attribs[1].componentCount          = iopairs[ioNdx].componentCount;
457                         spec.attribs[1].offset                          = 0;
458                         spec.attribs[1].stride                          = 0;
459                         spec.attribs[1].normalize                       = false;
460                         spec.attribs[1].instanceDivisor         = 0;
461                         spec.attribs[1].useDefaultAttribute     = true;
462
463                         test->addIteration(spec, desc.c_str());
464                 }
465
466                 this->addChild(test);
467         }
468 }
469
470 class IndexGroup : public TestCaseGroup
471 {
472 public:
473                                                                         IndexGroup              (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
474                                                                         ~IndexGroup             (void);
475
476         void                                                    init                    (void);
477
478 private:
479         gls::DrawTestSpec::DrawMethod   m_method;
480 };
481
482 IndexGroup::IndexGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
483         : TestCaseGroup         (context, name, descr)
484         , m_method                      (drawMethod)
485 {
486 }
487
488 IndexGroup::~IndexGroup (void)
489 {
490 }
491
492 void IndexGroup::init (void)
493 {
494         struct IndexTest
495         {
496                 gls::DrawTestSpec::IndexType    type;
497                 int                                                             offsets[3];
498         };
499
500         const IndexTest tests[] =
501         {
502                 { gls::DrawTestSpec::INDEXTYPE_BYTE,    { 0, 1, -1 } },
503                 { gls::DrawTestSpec::INDEXTYPE_SHORT,   { 0, 2, -1 } },
504                 { gls::DrawTestSpec::INDEXTYPE_INT,             { 0, 4, -1 } },
505         };
506
507         gls::DrawTestSpec spec;
508         genBasicSpec(spec, m_method);
509
510         spec.indexStorage = gls::DrawTestSpec::STORAGE_BUFFER;
511
512         for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(tests); ++testNdx)
513         {
514                 const IndexTest&        indexTest       = tests[testNdx];
515
516                 const std::string       name            = std::string("index_") + gls::DrawTestSpec::indexTypeToString(indexTest.type);
517                 const std::string       desc            = std::string("index ") + gls::DrawTestSpec::indexTypeToString(indexTest.type);
518                 gls::DrawTest*          test            = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), name.c_str(), desc.c_str());
519
520                 spec.indexType                  = indexTest.type;
521
522                 for (int iterationNdx = 0; iterationNdx < DE_LENGTH_OF_ARRAY(indexTest.offsets) && indexTest.offsets[iterationNdx] != -1; ++iterationNdx)
523                 {
524                         const std::string iterationDesc = std::string("first vertex ") + de::toString(indexTest.offsets[iterationNdx] / gls::DrawTestSpec::indexTypeSize(indexTest.type));
525                         spec.indexPointerOffset = indexTest.offsets[iterationNdx];
526                         test->addIteration(spec, iterationDesc.c_str());
527                 }
528
529                 addChild(test);
530         }
531 }
532
533 class BaseVertexGroup : public TestCaseGroup
534 {
535 public:
536                                                                         BaseVertexGroup         (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
537                                                                         ~BaseVertexGroup        (void);
538
539         void                                                    init                            (void);
540
541 private:
542         gls::DrawTestSpec::DrawMethod   m_method;
543 };
544
545 BaseVertexGroup::BaseVertexGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
546         : TestCaseGroup         (context, name, descr)
547         , m_method                      (drawMethod)
548 {
549 }
550
551 BaseVertexGroup::~BaseVertexGroup (void)
552 {
553 }
554
555 void BaseVertexGroup::init (void)
556 {
557         struct IndexTest
558         {
559                 bool                                                    positiveBase;
560                 gls::DrawTestSpec::IndexType    type;
561                 int                                                             baseVertex[2];
562         };
563
564         const IndexTest tests[] =
565         {
566                 { true,  gls::DrawTestSpec::INDEXTYPE_BYTE,             {  1,  2 } },
567                 { true,  gls::DrawTestSpec::INDEXTYPE_SHORT,    {  1,  2 } },
568                 { true,  gls::DrawTestSpec::INDEXTYPE_INT,              {  1,  2 } },
569                 { false, gls::DrawTestSpec::INDEXTYPE_BYTE,             { -1, -2 } },
570                 { false, gls::DrawTestSpec::INDEXTYPE_SHORT,    { -1, -2 } },
571                 { false, gls::DrawTestSpec::INDEXTYPE_INT,              { -1, -2 } },
572         };
573
574         gls::DrawTestSpec spec;
575         genBasicSpec(spec, m_method);
576
577         spec.indexStorage = gls::DrawTestSpec::STORAGE_BUFFER;
578
579         for (int testNdx = 0; testNdx < DE_LENGTH_OF_ARRAY(tests); ++testNdx)
580         {
581                 const IndexTest&        indexTest       = tests[testNdx];
582
583                 const std::string       name            = std::string("index_") + (indexTest.positiveBase ? "" : "neg_") + gls::DrawTestSpec::indexTypeToString(indexTest.type);
584                 const std::string       desc            = std::string("index ") + gls::DrawTestSpec::indexTypeToString(indexTest.type);
585                 gls::DrawTest*          test            = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), name.c_str(), desc.c_str());
586
587                 spec.indexType                  = indexTest.type;
588
589                 for (int iterationNdx = 0; iterationNdx < DE_LENGTH_OF_ARRAY(indexTest.baseVertex); ++iterationNdx)
590                 {
591                         const std::string iterationDesc = std::string("base vertex ") + de::toString(indexTest.baseVertex[iterationNdx]);
592                         spec.baseVertex = indexTest.baseVertex[iterationNdx];
593                         test->addIteration(spec, iterationDesc.c_str());
594                 }
595
596                 addChild(test);
597         }
598 }
599
600 class FirstGroup : public TestCaseGroup
601 {
602 public:
603                                                                         FirstGroup              (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
604                                                                         ~FirstGroup             (void);
605
606         void                                                    init                    (void);
607
608 private:
609         gls::DrawTestSpec::DrawMethod   m_method;
610 };
611
612 FirstGroup::FirstGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
613         : TestCaseGroup         (context, name, descr)
614         , m_method                      (drawMethod)
615 {
616 }
617
618 FirstGroup::~FirstGroup (void)
619 {
620 }
621
622 void FirstGroup::init (void)
623 {
624         const int firsts[] =
625         {
626                 1, 3, 17
627         };
628
629         gls::DrawTestSpec spec;
630         genBasicSpec(spec, m_method);
631
632         for (int firstNdx = 0; firstNdx < DE_LENGTH_OF_ARRAY(firsts); ++firstNdx)
633         {
634                 const std::string       name = std::string("first_") + de::toString(firsts[firstNdx]);
635                 const std::string       desc = std::string("first ") + de::toString(firsts[firstNdx]);
636                 gls::DrawTest*          test = new gls::DrawTest(m_testCtx, m_context.getRenderContext(), name.c_str(), desc.c_str());
637
638                 spec.first = firsts[firstNdx];
639
640                 addTestIterations(test, spec, TYPE_DRAW_COUNT);
641
642                 this->addChild(test);
643         }
644 }
645
646 class MethodGroup : public TestCaseGroup
647 {
648 public:
649                                                                         MethodGroup                     (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod);
650                                                                         ~MethodGroup            (void);
651
652         void                                                    init                            (void);
653
654 private:
655         gls::DrawTestSpec::DrawMethod   m_method;
656 };
657
658 MethodGroup::MethodGroup (Context& context, const char* name, const char* descr, gls::DrawTestSpec::DrawMethod drawMethod)
659         : TestCaseGroup         (context, name, descr)
660         , m_method                      (drawMethod)
661 {
662 }
663
664 MethodGroup::~MethodGroup (void)
665 {
666 }
667
668 void MethodGroup::init (void)
669 {
670         const bool indexed              = (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INDIRECT);
671         const bool hasFirst             = (m_method == gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS_INDIRECT);
672
673         const gls::DrawTestSpec::Primitive primitive[] =
674         {
675                 gls::DrawTestSpec::PRIMITIVE_POINTS,
676                 gls::DrawTestSpec::PRIMITIVE_TRIANGLES,
677                 gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN,
678                 gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP,
679                 gls::DrawTestSpec::PRIMITIVE_LINES,
680                 gls::DrawTestSpec::PRIMITIVE_LINE_STRIP,
681                 gls::DrawTestSpec::PRIMITIVE_LINE_LOOP
682         };
683
684         if (hasFirst)
685         {
686                 // First-tests
687                 this->addChild(new FirstGroup(m_context, "first", "First tests", m_method));
688         }
689
690         if (indexed)
691         {
692                 // Index-tests
693                 this->addChild(new IndexGroup(m_context, "indices", "Index tests", m_method));
694                 this->addChild(new BaseVertexGroup(m_context, "base_vertex", "Base vertex tests", m_method));
695         }
696
697         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(primitive); ++ndx)
698         {
699                 const std::string name = gls::DrawTestSpec::primitiveToString(primitive[ndx]);
700                 const std::string desc = gls::DrawTestSpec::primitiveToString(primitive[ndx]);
701
702                 this->addChild(new AttributeGroup(m_context, name.c_str(), desc.c_str(), m_method, primitive[ndx], gls::DrawTestSpec::INDEXTYPE_SHORT, gls::DrawTestSpec::STORAGE_BUFFER));
703         }
704 }
705
706 class GridProgram : public sglr::ShaderProgram
707 {
708 public:
709                         GridProgram             (void);
710
711         void    shadeVertices   (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const;
712         void    shadeFragments  (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const;
713 };
714
715 GridProgram::GridProgram (void)
716         : sglr::ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
717                                                         << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
718                                                         << sglr::pdec::VertexAttribute("a_offset", rr::GENERICVECTYPE_FLOAT)
719                                                         << sglr::pdec::VertexAttribute("a_color", rr::GENERICVECTYPE_FLOAT)
720                                                         << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
721                                                         << sglr::pdec::FragmentOutput(rr::GENERICVECTYPE_FLOAT)
722                                                         << sglr::pdec::VertexSource("#version 310 es\n"
723                                                                                                                 "in highp vec4 a_position;\n"
724                                                                                                                 "in highp vec4 a_offset;\n"
725                                                                                                                 "in highp vec4 a_color;\n"
726                                                                                                                 "out highp vec4 v_color;\n"
727                                                                                                                 "void main(void)\n"
728                                                                                                                 "{\n"
729                                                                                                                 "       gl_Position = a_position + a_offset;\n"
730                                                                                                                 "       v_color = a_color;\n"
731                                                                                                                 "}\n")
732                                                         << sglr::pdec::FragmentSource(
733                                                                                                                 "#version 310 es\n"
734                                                                                                                 "layout(location = 0) out highp vec4 dEQP_FragColor;\n"
735                                                                                                                 "in highp vec4 v_color;\n"
736                                                                                                                 "void main(void)\n"
737                                                                                                                 "{\n"
738                                                                                                                 "       dEQP_FragColor = v_color;\n"
739                                                                                                                 "}\n"))
740 {
741 }
742
743 void GridProgram::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
744 {
745         for (int ndx = 0; ndx < numPackets; ++ndx)
746         {
747                 packets[ndx]->position = rr::readVertexAttribFloat(inputs[0], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx) + rr::readVertexAttribFloat(inputs[1], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx);
748                 packets[ndx]->outputs[0] = rr::readVertexAttribFloat(inputs[2], packets[ndx]->instanceNdx, packets[ndx]->vertexNdx);
749         }
750 }
751
752 void GridProgram::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
753 {
754         for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
755         for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
756                 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, rr::readTriangleVarying<float>(packets[packetNdx], context, 0, fragNdx));
757 }
758
759 class InstancedGridRenderTest : public TestCase
760 {
761 public:
762                                         InstancedGridRenderTest         (Context& context, const char* name, const char* desc, int gridSide, bool useIndices);
763                                         ~InstancedGridRenderTest        (void);
764
765         IterateResult   iterate                                         (void);
766
767 private:
768         void                    renderTo                                        (sglr::Context& ctx, sglr::ShaderProgram& program, tcu::Surface& dst);
769
770         const int               m_gridSide;
771         const bool              m_useIndices;
772 };
773
774 InstancedGridRenderTest::InstancedGridRenderTest (Context& context, const char* name, const char* desc, int gridSide, bool useIndices)
775         : TestCase              (context, name, desc)
776         , m_gridSide    (gridSide)
777         , m_useIndices  (useIndices)
778 {
779 }
780
781 InstancedGridRenderTest::~InstancedGridRenderTest (void)
782 {
783 }
784
785 InstancedGridRenderTest::IterateResult InstancedGridRenderTest::iterate (void)
786 {
787         const int renderTargetWidth  = de::min(1024, m_context.getRenderTarget().getWidth());
788         const int renderTargetHeight = de::min(1024, m_context.getRenderTarget().getHeight());
789
790         sglr::GLContext ctx             (m_context.getRenderContext(), m_testCtx.getLog(), sglr::GLCONTEXT_LOG_CALLS | sglr::GLCONTEXT_LOG_PROGRAMS, tcu::IVec4(0, 0, renderTargetWidth, renderTargetHeight));
791         tcu::Surface    surface (renderTargetWidth, renderTargetHeight);
792         GridProgram             program;
793
794         // render
795
796         renderTo(ctx, program, surface);
797
798         // verify image
799         // \note the green/yellow pattern is only for clarity. The test will only verify that all instances were drawn by looking for anything non-green/yellow.
800         if (verifyImageYellowGreen(surface, m_testCtx.getLog()))
801                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
802         else
803                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Result image invalid");
804         return STOP;
805 }
806
807 void InstancedGridRenderTest::renderTo (sglr::Context& ctx, sglr::ShaderProgram& program, tcu::Surface& dst)
808 {
809         const tcu::Vec4 green   (0, 1, 0, 1);
810         const tcu::Vec4 yellow  (1, 1, 0, 1);
811
812         deUint32 vaoID                  = 0;
813         deUint32 positionBuf    = 0;
814         deUint32 offsetBuf              = 0;
815         deUint32 colorBuf               = 0;
816         deUint32 indexBuf               = 0;
817         deUint32 drawIndirectBuf= 0;
818         deUint32 programID              = ctx.createProgram(&program);
819         deInt32 posLocation             = ctx.getAttribLocation(programID, "a_position");
820         deInt32 offsetLocation  = ctx.getAttribLocation(programID, "a_offset");
821         deInt32 colorLocation   = ctx.getAttribLocation(programID, "a_color");
822
823         float cellW     = 2.0f / (float)m_gridSide;
824         float cellH     = 2.0f / (float)m_gridSide;
825         const tcu::Vec4 vertexPositions[] =
826         {
827                 tcu::Vec4(0,            0,              0, 1),
828                 tcu::Vec4(cellW,        0,              0, 1),
829                 tcu::Vec4(0,            cellH,  0, 1),
830
831                 tcu::Vec4(0,            cellH,  0, 1),
832                 tcu::Vec4(cellW,        0,              0, 1),
833                 tcu::Vec4(cellW,        cellH,  0, 1),
834         };
835
836         const deUint16 indices[] =
837         {
838                 0, 4, 3,
839                 2, 1, 5
840         };
841
842         std::vector<tcu::Vec4> offsets;
843         for (int x = 0; x < m_gridSide; ++x)
844         for (int y = 0; y < m_gridSide; ++y)
845                 offsets.push_back(tcu::Vec4((float)x * cellW - 1.0f, (float)y * cellW - 1.0f, 0, 0));
846
847         std::vector<tcu::Vec4> colors;
848         for (int x = 0; x < m_gridSide; ++x)
849         for (int y = 0; y < m_gridSide; ++y)
850                 colors.push_back(((x + y) % 2 == 0) ? (green) : (yellow));
851
852         ctx.genVertexArrays(1, &vaoID);
853         ctx.bindVertexArray(vaoID);
854
855         ctx.genBuffers(1, &positionBuf);
856         ctx.bindBuffer(GL_ARRAY_BUFFER, positionBuf);
857         ctx.bufferData(GL_ARRAY_BUFFER, sizeof(vertexPositions), vertexPositions, GL_STATIC_DRAW);
858         ctx.vertexAttribPointer(posLocation, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
859         ctx.vertexAttribDivisor(posLocation, 0);
860         ctx.enableVertexAttribArray(posLocation);
861
862         ctx.genBuffers(1, &offsetBuf);
863         ctx.bindBuffer(GL_ARRAY_BUFFER, offsetBuf);
864         ctx.bufferData(GL_ARRAY_BUFFER, offsets.size() * sizeof(tcu::Vec4), &offsets[0], GL_STATIC_DRAW);
865         ctx.vertexAttribPointer(offsetLocation, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
866         ctx.vertexAttribDivisor(offsetLocation, 1);
867         ctx.enableVertexAttribArray(offsetLocation);
868
869         ctx.genBuffers(1, &colorBuf);
870         ctx.bindBuffer(GL_ARRAY_BUFFER, colorBuf);
871         ctx.bufferData(GL_ARRAY_BUFFER, colors.size() * sizeof(tcu::Vec4), &colors[0], GL_STATIC_DRAW);
872         ctx.vertexAttribPointer(colorLocation, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
873         ctx.vertexAttribDivisor(colorLocation, 1);
874         ctx.enableVertexAttribArray(colorLocation);
875
876         if (m_useIndices)
877         {
878                 ctx.genBuffers(1, &indexBuf);
879                 ctx.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuf);
880                 ctx.bufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
881         }
882
883         ctx.genBuffers(1, &drawIndirectBuf);
884         ctx.bindBuffer(GL_DRAW_INDIRECT_BUFFER, drawIndirectBuf);
885
886         if (m_useIndices)
887         {
888                 DrawElementsCommand command;
889                 command.count                           = 6;
890                 command.primCount                       = m_gridSide * m_gridSide;
891                 command.firstIndex                      = 0;
892                 command.baseVertex                      = 0;
893                 command.reservedMustBeZero      = 0;
894
895                 ctx.bufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(command), &command, GL_STATIC_DRAW);
896         }
897         else
898         {
899                 DrawArraysCommand command;
900                 command.count                           = 6;
901                 command.primCount                       = m_gridSide * m_gridSide;
902                 command.first                           = 0;
903                 command.reservedMustBeZero      = 0;
904
905                 ctx.bufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(command), &command, GL_STATIC_DRAW);
906         }
907
908         ctx.clearColor(0, 0, 0, 1);
909         ctx.clear(GL_COLOR_BUFFER_BIT);
910
911         ctx.viewport(0, 0, dst.getWidth(), dst.getHeight());
912
913         ctx.useProgram(programID);
914         if (m_useIndices)
915                 ctx.drawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, DE_NULL);
916         else
917                 ctx.drawArraysIndirect(GL_TRIANGLES, DE_NULL);
918         ctx.useProgram(0);
919
920         glu::checkError(ctx.getError(), "", __FILE__, __LINE__);
921
922         ctx.deleteBuffers(1, &drawIndirectBuf);
923         if (m_useIndices)
924                 ctx.deleteBuffers(1, &indexBuf);
925         ctx.deleteBuffers(1, &colorBuf);
926         ctx.deleteBuffers(1, &offsetBuf);
927         ctx.deleteBuffers(1, &positionBuf);
928         ctx.deleteVertexArrays(1, &vaoID);
929         ctx.deleteProgram(programID);
930
931         ctx.finish();
932         ctx.readPixels(dst, 0, 0, dst.getWidth(), dst.getHeight());
933
934         glu::checkError(ctx.getError(), "", __FILE__, __LINE__);
935 }
936
937 class InstancingGroup : public TestCaseGroup
938 {
939 public:
940                         InstancingGroup         (Context& context, const char* name, const char* descr);
941                         ~InstancingGroup        (void);
942
943         void    init                            (void);
944 };
945
946 InstancingGroup::InstancingGroup (Context& context, const char* name, const char* descr)
947         : TestCaseGroup (context, name, descr)
948 {
949 }
950
951 InstancingGroup::~InstancingGroup (void)
952 {
953 }
954
955 void InstancingGroup::init (void)
956 {
957         const int gridWidths[] =
958         {
959                 2,
960                 5,
961                 10,
962                 32,
963                 100,
964         };
965
966         // drawArrays
967         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(gridWidths); ++ndx)
968         {
969                 const std::string name = std::string("draw_arrays_indirect_grid_") + de::toString(gridWidths[ndx]) + "x" + de::toString(gridWidths[ndx]);
970                 const std::string desc = std::string("DrawArraysIndirect, Grid size ") + de::toString(gridWidths[ndx]) + "x" + de::toString(gridWidths[ndx]);
971
972                 this->addChild(new InstancedGridRenderTest(m_context, name.c_str(), desc.c_str(), gridWidths[ndx], false));
973         }
974
975         // drawElements
976         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(gridWidths); ++ndx)
977         {
978                 const std::string name = std::string("draw_elements_indirect_grid_") + de::toString(gridWidths[ndx]) + "x" + de::toString(gridWidths[ndx]);
979                 const std::string desc = std::string("DrawElementsIndirect, Grid size ") + de::toString(gridWidths[ndx]) + "x" + de::toString(gridWidths[ndx]);
980
981                 this->addChild(new InstancedGridRenderTest(m_context, name.c_str(), desc.c_str(), gridWidths[ndx], true));
982         }
983 }
984
985 class ComputeShaderGeneratedCase : public TestCase
986 {
987 public:
988         enum DrawMethod
989         {
990                 DRAWMETHOD_DRAWARRAYS,
991                 DRAWMETHOD_DRAWELEMENTS,
992                 DRAWMETHOD_LAST
993         };
994
995                                                 ComputeShaderGeneratedCase      (Context& context, const char* name, const char* desc, DrawMethod method, bool computeCmd, bool computeData, bool computeIndices, int gridSize, int drawCallCount);
996                                                 ~ComputeShaderGeneratedCase     (void);
997         void                            init                                            (void);
998         void                            deinit                                          (void);
999
1000         IterateResult           iterate                                         (void);
1001         std::string                     genComputeSource                        (bool computeCmd, bool computeData, bool computeIndices) const;
1002
1003 private:
1004         void                            createDrawCommand                       (void);
1005         void                            createDrawData                          (void);
1006         void                            createDrawIndices                       (void);
1007
1008         virtual void            runComputeShader                        (void) = 0;
1009         void                            renderTo                                        (tcu::Surface& image);
1010
1011 protected:
1012         deUint32                        calcDrawBufferSize                      (void) const;
1013         deUint32                        calcIndexBufferSize                     (void) const;
1014
1015         const DrawMethod        m_drawMethod;
1016         const bool                      m_computeCmd;
1017         const bool                      m_computeData;
1018         const bool                      m_computeIndices;
1019         const int                       m_commandSize;
1020         const int                       m_numDrawCmds;
1021         const int                       m_gridSize;
1022
1023         glw::GLuint                     m_cmdBufferID;
1024         glw::GLuint                     m_dataBufferID;
1025         glw::GLuint                     m_indexBufferID;
1026
1027 private:
1028         glu::ShaderProgram*     m_shaderProgram;
1029 };
1030
1031 ComputeShaderGeneratedCase::ComputeShaderGeneratedCase (Context& context, const char* name, const char* desc, DrawMethod method, bool computeCmd, bool computeData, bool computeIndices, int gridSize, int drawCallCount)
1032         : TestCase                      (context, name, desc)
1033         , m_drawMethod          (method)
1034         , m_computeCmd          (computeCmd)
1035         , m_computeData         (computeData)
1036         , m_computeIndices      (computeIndices)
1037         , m_commandSize         ((method==DRAWMETHOD_DRAWARRAYS) ? ((int)sizeof(DrawArraysCommand)) : ((int)sizeof(DrawElementsCommand)))
1038         , m_numDrawCmds         (drawCallCount)
1039         , m_gridSize            (gridSize)
1040         , m_cmdBufferID         (0)
1041         , m_dataBufferID        (0)
1042         , m_indexBufferID       (0)
1043         , m_shaderProgram       (DE_NULL)
1044 {
1045     const int triangleCount     = m_gridSize * m_gridSize * 2;
1046
1047         DE_ASSERT(method < DRAWMETHOD_LAST);
1048         DE_ASSERT(!computeIndices || method == DRAWMETHOD_DRAWELEMENTS);
1049         DE_ASSERT(triangleCount % m_numDrawCmds == 0);
1050         DE_UNREF(triangleCount);
1051 }
1052
1053 ComputeShaderGeneratedCase::~ComputeShaderGeneratedCase (void)
1054 {
1055         deinit();
1056 }
1057
1058 void ComputeShaderGeneratedCase::init (void)
1059 {
1060         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1061
1062         // generate basic shader
1063
1064         m_shaderProgram = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() << glu::VertexSource(s_colorVertexShaderSource) << glu::FragmentSource(s_colorFragmentShaderSource));
1065         m_testCtx.getLog() << *m_shaderProgram;
1066
1067         if (!m_shaderProgram->isOk())
1068                 throw tcu::TestError("Failed to compile shader.");
1069
1070         // gen buffers
1071         gl.genBuffers(1, &m_cmdBufferID);
1072         gl.genBuffers(1, &m_dataBufferID);
1073         gl.genBuffers(1, &m_indexBufferID);
1074
1075         // check the SSBO buffers are of legal size
1076         {
1077                 const deUint64  drawBufferElementSize   = sizeof(tcu::Vec4);
1078                 const deUint64  indexBufferElementSize  = sizeof(deUint32);
1079                 const int               commandBufferSize               = m_commandSize * m_numDrawCmds;
1080                 deInt64                 maxSSBOSize                             = 0;
1081
1082                 gl.getInteger64v(GL_MAX_SHADER_STORAGE_BLOCK_SIZE, &maxSSBOSize);
1083
1084                 if (m_computeData && (deUint64)calcDrawBufferSize()*drawBufferElementSize > (deUint64)maxSSBOSize)
1085                         throw tcu::NotSupportedError("GL_MAX_SHADER_STORAGE_BLOCK_SIZE is too small for vertex attrib buffers");
1086                 if (m_computeIndices && (deUint64)calcIndexBufferSize()*indexBufferElementSize > (deUint64)maxSSBOSize)
1087                         throw tcu::NotSupportedError("GL_MAX_SHADER_STORAGE_BLOCK_SIZE is too small for index buffers");
1088                 if (m_computeCmd && (deUint64)commandBufferSize > (deUint64)maxSSBOSize)
1089                         throw tcu::NotSupportedError("GL_MAX_SHADER_STORAGE_BLOCK_SIZE is too small for command buffers");
1090         }
1091 }
1092
1093 void ComputeShaderGeneratedCase::deinit (void)
1094 {
1095         if (m_cmdBufferID)
1096         {
1097                 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_cmdBufferID);
1098                 m_cmdBufferID = 0;
1099         }
1100         if (m_dataBufferID)
1101         {
1102                 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_dataBufferID);
1103                 m_dataBufferID = 0;
1104         }
1105         if (m_indexBufferID)
1106         {
1107                 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_indexBufferID);
1108                 m_indexBufferID = 0;
1109         }
1110
1111         if (m_shaderProgram)
1112         {
1113                 delete m_shaderProgram;
1114                 m_shaderProgram = DE_NULL;
1115         }
1116 }
1117
1118 ComputeShaderGeneratedCase::IterateResult ComputeShaderGeneratedCase::iterate (void)
1119 {
1120         const int                               renderTargetWidth       = de::min(1024, m_context.getRenderTarget().getWidth());
1121         const int                               renderTargetHeight      = de::min(1024, m_context.getRenderTarget().getHeight());
1122         const glw::Functions&   gl                                      = m_context.getRenderContext().getFunctions();
1123         tcu::Surface                    surface                         (renderTargetWidth, renderTargetHeight);
1124
1125         m_testCtx.getLog() << tcu::TestLog::Message << "Preparing to draw " << m_gridSize << " x " << m_gridSize << " grid." << tcu::TestLog::EndMessage;
1126
1127         try
1128         {
1129                 // Gen command buffer
1130                 if (!m_computeCmd)
1131                 {
1132                         m_testCtx.getLog() << tcu::TestLog::Message << "Uploading draw command buffer." << tcu::TestLog::EndMessage;
1133                         createDrawCommand();
1134                 }
1135
1136                 // Gen data buffer
1137                 if (!m_computeData)
1138                 {
1139                         m_testCtx.getLog() << tcu::TestLog::Message << "Uploading draw data buffer." << tcu::TestLog::EndMessage;
1140                         createDrawData();
1141                 }
1142
1143                 // Gen index buffer
1144                 if (!m_computeIndices && m_drawMethod == DRAWMETHOD_DRAWELEMENTS)
1145                 {
1146                         m_testCtx.getLog() << tcu::TestLog::Message << "Uploading draw index buffer." << tcu::TestLog::EndMessage;
1147                         createDrawIndices();
1148                 }
1149
1150                 // Run compute shader
1151                 {
1152                         m_testCtx.getLog()
1153                                 << tcu::TestLog::Message << "Filling following buffers using compute shader:\n"
1154                                 << ((m_computeCmd)              ? ("\tcommand buffer\n")        : (""))
1155                                 << ((m_computeData)             ? ("\tdata buffer\n")           : (""))
1156                                 << ((m_computeIndices)  ? ("\tindex buffer\n")          : (""))
1157                                 << tcu::TestLog::EndMessage;
1158                         runComputeShader();
1159                 }
1160
1161                 // Ensure data is written to the buffers before we try to read it
1162                 {
1163                         const glw::GLuint barriers = ((m_computeCmd)     ? (GL_COMMAND_BARRIER_BIT)             : (0)) |
1164                                                                                  ((m_computeData)    ? (GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT) : (0)) |
1165                                                                                  ((m_computeIndices) ? (GL_ELEMENT_ARRAY_BARRIER_BIT)       : (0));
1166
1167                         m_testCtx.getLog() << tcu::TestLog::Message << "Memory barrier. Barriers = " << glu::getMemoryBarrierFlagsStr(barriers) << tcu::TestLog::EndMessage;
1168                         gl.memoryBarrier(barriers);
1169                 }
1170
1171                 // Draw from buffers
1172
1173                 m_testCtx.getLog() << tcu::TestLog::Message << "Drawing from buffers with " << m_numDrawCmds << " draw call(s)." << tcu::TestLog::EndMessage;
1174                 renderTo(surface);
1175         }
1176         catch (glu::OutOfMemoryError&)
1177         {
1178                 m_testCtx.getLog() << tcu::TestLog::Message << "Got GL_OUT_OF_MEMORY." << tcu::TestLog::EndMessage;
1179                 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Got GL_OUT_OF_MEMORY");
1180                 m_testCtx.setTerminateAfter(true); // Do not rely on implementation to be able to recover from OOM
1181                 return STOP;
1182         }
1183
1184
1185         // verify image
1186         // \note the green/yellow pattern is only for clarity. The test will only verify that all grid cells were drawn by looking for anything non-green/yellow.
1187         if (verifyImageYellowGreen(surface, m_testCtx.getLog()))
1188                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1189         else
1190                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Result image invalid");
1191         return STOP;
1192 }
1193
1194 std::string ComputeShaderGeneratedCase::genComputeSource (bool computeCmd, bool computeData, bool computeIndices) const
1195 {
1196         const int cmdLayoutBinding                              = 0;
1197         const int dataLayoutBinding                             = (computeCmd) ? (1) : (0);
1198         const int indexLayoutBinding                    = (computeCmd && computeData) ? (2) : (computeCmd || computeData) ? (1) : (0);
1199
1200         std::ostringstream buf;
1201
1202         buf << "#version 310 es\n\n"
1203                 << "precision highp int;\n"
1204                 << "precision highp float;\n\n";
1205
1206         if (computeCmd && m_drawMethod==DRAWMETHOD_DRAWARRAYS)
1207                 buf     << "struct DrawArraysIndirectCommand {\n"
1208                         << "    uint count;\n"
1209                         << "    uint primCount;\n"
1210                         << "    uint first;\n"
1211                         << "    uint reservedMustBeZero;\n"
1212                         << "};\n\n";
1213         else if (computeCmd && m_drawMethod==DRAWMETHOD_DRAWELEMENTS)
1214                 buf     << "struct DrawElementsIndirectCommand {\n"
1215                         << "    uint count;\n"
1216                         << "    uint primCount;\n"
1217                         << "    uint firstIndex;\n"
1218                         << "    int  baseVertex;\n"
1219                         << "    uint reservedMustBeZero;\n"
1220                         << "};\n\n";
1221
1222         buf << "layout(local_size_x = 1, local_size_y = 1) in;\n"
1223                 << "layout(std430) buffer;\n\n";
1224
1225         if (computeCmd)
1226                 buf     << "layout(binding = " << cmdLayoutBinding << ") writeonly buffer CommandBuffer {\n"
1227                         << "    " << ((m_drawMethod==DRAWMETHOD_DRAWARRAYS) ? ("DrawArraysIndirectCommand") : ("DrawElementsIndirectCommand")) << " commands[];\n"
1228                         << "};\n";
1229         if (computeData)
1230                 buf     << "layout(binding = " << dataLayoutBinding << ") writeonly buffer DataBuffer {\n"
1231                         << "    vec4 attribs[];\n"
1232                         << "};\n";
1233         if (computeIndices)
1234                 buf     << "layout(binding = " << indexLayoutBinding << ") writeonly buffer IndexBuffer {\n"
1235                         << "    uint indices[];\n"
1236                         << "};\n";
1237
1238         buf     << "\n"
1239                 << "void main() {\n"
1240                 << "    const uint gridSize      = " << m_gridSize << "u;\n"
1241                 << "    const uint triangleCount = gridSize * gridSize * 2u;\n"
1242                 << "\n";
1243
1244         if (computeCmd)
1245         {
1246                 buf     << "    // command\n"
1247                         << "    if (gl_GlobalInvocationID.x < " << m_numDrawCmds << "u && gl_GlobalInvocationID.y == 0u && gl_GlobalInvocationID.z == 0u) {\n"
1248                         << "        const uint numDrawCallTris = triangleCount / " << m_numDrawCmds << "u;\n"
1249                         << "        uint firstTri              = gl_GlobalInvocationID.x * numDrawCallTris;\n\n"
1250                         << "        commands[gl_GlobalInvocationID.x].count                 = numDrawCallTris*3u;\n"
1251                         << "        commands[gl_GlobalInvocationID.x].primCount             = 1u;\n";
1252
1253                 if (m_drawMethod==DRAWMETHOD_DRAWARRAYS)
1254                 {
1255                         buf     << "        commands[gl_GlobalInvocationID.x].first                 = firstTri*3u;\n";
1256                 }
1257                 else if (m_drawMethod==DRAWMETHOD_DRAWELEMENTS)
1258                 {
1259                         buf     << "        commands[gl_GlobalInvocationID.x].firstIndex            = firstTri*3u;\n";
1260                         buf     << "        commands[gl_GlobalInvocationID.x].baseVertex            = 0;\n";
1261                 }
1262
1263                 buf     << "        commands[gl_GlobalInvocationID.x].reservedMustBeZero    = 0u;\n"
1264                         << "    }\n"
1265                         << "\n";
1266         }
1267
1268         if (computeData)
1269         {
1270                 buf     << "    // vertex attribs\n"
1271                         << "    const vec4 yellow = vec4(1.0, 1.0, 0.0, 1.0);\n"
1272                         << "    const vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n";
1273
1274                 if (m_drawMethod == DRAWMETHOD_DRAWARRAYS)
1275                 {
1276                         buf     << "    if (gl_GlobalInvocationID.x < gridSize && gl_GlobalInvocationID.y < gridSize && gl_GlobalInvocationID.z == 0u) {\n"
1277                                 << "        uint        y           = gl_GlobalInvocationID.x;\n"
1278                                 << "        uint        x           = gl_GlobalInvocationID.y;\n"
1279                                 << "        float       posX        = (float(x) / float(gridSize)) * 2.0 - 1.0;\n"
1280                                 << "        float       posY        = (float(y) / float(gridSize)) * 2.0 - 1.0;\n"
1281                                 << "        const float cellSize    = 2.0 / float(gridSize);\n"
1282                                 << "        vec4        color       = ((x + y)%2u != 0u) ? (yellow) : (green);\n"
1283                                 << "\n"
1284                                 << "        attribs[((y * gridSize + x) * 6u + 0u) * 2u + 0u] = vec4(posX,            posY,            0.0, 1.0);\n"
1285                                 << "        attribs[((y * gridSize + x) * 6u + 1u) * 2u + 0u] = vec4(posX + cellSize, posY,            0.0, 1.0);\n"
1286                                 << "        attribs[((y * gridSize + x) * 6u + 2u) * 2u + 0u] = vec4(posX + cellSize, posY + cellSize, 0.0, 1.0);\n"
1287                                 << "        attribs[((y * gridSize + x) * 6u + 3u) * 2u + 0u] = vec4(posX,            posY,            0.0, 1.0);\n"
1288                                 << "        attribs[((y * gridSize + x) * 6u + 4u) * 2u + 0u] = vec4(posX + cellSize, posY + cellSize, 0.0, 1.0);\n"
1289                                 << "        attribs[((y * gridSize + x) * 6u + 5u) * 2u + 0u] = vec4(posX,            posY + cellSize, 0.0, 1.0);\n"
1290                                 << "\n"
1291                                 << "        attribs[((y * gridSize + x) * 6u + 0u) * 2u + 1u] = color;\n"
1292                                 << "        attribs[((y * gridSize + x) * 6u + 1u) * 2u + 1u] = color;\n"
1293                                 << "        attribs[((y * gridSize + x) * 6u + 2u) * 2u + 1u] = color;\n"
1294                                 << "        attribs[((y * gridSize + x) * 6u + 3u) * 2u + 1u] = color;\n"
1295                                 << "        attribs[((y * gridSize + x) * 6u + 4u) * 2u + 1u] = color;\n"
1296                                 << "        attribs[((y * gridSize + x) * 6u + 5u) * 2u + 1u] = color;\n"
1297                                 << "    }\n";
1298                 }
1299                 else if (m_drawMethod == DRAWMETHOD_DRAWELEMENTS)
1300                 {
1301                         buf     << "    if (gl_GlobalInvocationID.x < gridSize+1u && gl_GlobalInvocationID.y < gridSize+1u && gl_GlobalInvocationID.z == 0u) {\n"
1302                                 << "        uint        y           = gl_GlobalInvocationID.x;\n"
1303                                 << "        uint        x           = gl_GlobalInvocationID.y;\n"
1304                                 << "        float       posX        = (float(x) / float(gridSize)) * 2.0 - 1.0;\n"
1305                                 << "        float       posY        = (float(y) / float(gridSize)) * 2.0 - 1.0;\n"
1306                                 << "\n"
1307                                 << "        attribs[(y * (gridSize+1u) + x) * 4u + 0u] = vec4(posX, posY, 0.0, 1.0);\n"
1308                                 << "        attribs[(y * (gridSize+1u) + x) * 4u + 1u] = green;\n"
1309                                 << "        attribs[(y * (gridSize+1u) + x) * 4u + 2u] = vec4(posX, posY, 0.0, 1.0);\n"
1310                                 << "        attribs[(y * (gridSize+1u) + x) * 4u + 3u] = yellow;\n"
1311                                 << "    }\n";
1312                 }
1313
1314                 buf << "\n";
1315         }
1316
1317         if (computeIndices)
1318         {
1319                 buf     << "    // indices\n"
1320                         << "    if (gl_GlobalInvocationID.x < gridSize && gl_GlobalInvocationID.y < gridSize && gl_GlobalInvocationID.z == 0u) {\n"
1321                         << "        uint    y       = gl_GlobalInvocationID.x;\n"
1322                         << "        uint    x       = gl_GlobalInvocationID.y;\n"
1323                         << "        uint    color   = ((x + y)%2u);\n"
1324                         << "\n"
1325                         << "        indices[(y * gridSize + x) * 6u + 0u] = ((y+0u) * (gridSize+1u) + (x+0u)) * 2u + color;\n"
1326                         << "        indices[(y * gridSize + x) * 6u + 1u] = ((y+1u) * (gridSize+1u) + (x+0u)) * 2u + color;\n"
1327                         << "        indices[(y * gridSize + x) * 6u + 2u] = ((y+1u) * (gridSize+1u) + (x+1u)) * 2u + color;\n"
1328                         << "        indices[(y * gridSize + x) * 6u + 3u] = ((y+0u) * (gridSize+1u) + (x+0u)) * 2u + color;\n"
1329                         << "        indices[(y * gridSize + x) * 6u + 4u] = ((y+1u) * (gridSize+1u) + (x+1u)) * 2u + color;\n"
1330                         << "        indices[(y * gridSize + x) * 6u + 5u] = ((y+0u) * (gridSize+1u) + (x+1u)) * 2u + color;\n"
1331                         << "    }\n"
1332                         << "\n";
1333         }
1334
1335         buf     << "}\n";
1336
1337         return buf.str();
1338 }
1339
1340 void ComputeShaderGeneratedCase::createDrawCommand (void)
1341 {
1342         const glw::Functions&   gl                              = m_context.getRenderContext().getFunctions();
1343         const int                               triangleCount   = m_gridSize * m_gridSize * 2;
1344         const deUint32                  numDrawCallTris = triangleCount / m_numDrawCmds;
1345
1346         if (m_drawMethod == DRAWMETHOD_DRAWARRAYS)
1347         {
1348                 std::vector<DrawArraysCommand> cmds;
1349
1350                 for (int ndx = 0; ndx < m_numDrawCmds; ++ndx)
1351                 {
1352                         const deUint32                          firstTri = ndx * numDrawCallTris;
1353                         DrawArraysCommand                       data;
1354
1355                         data.count                                      = numDrawCallTris*3;
1356                         data.primCount                          = 1;
1357                         data.first                                      = firstTri*3;
1358                         data.reservedMustBeZero         = 0;
1359
1360                         cmds.push_back(data);
1361                 }
1362
1363                 DE_ASSERT((int)(sizeof(DrawArraysCommand)*cmds.size()) == m_numDrawCmds * m_commandSize);
1364
1365                 gl.bindBuffer(GL_DRAW_INDIRECT_BUFFER, m_cmdBufferID);
1366                 gl.bufferData(GL_DRAW_INDIRECT_BUFFER, (glw::GLsizeiptr)(sizeof(DrawArraysCommand)*cmds.size()), &cmds[0], GL_STATIC_DRAW);
1367         }
1368         else if (m_drawMethod == DRAWMETHOD_DRAWELEMENTS)
1369         {
1370                 std::vector<DrawElementsCommand> cmds;
1371
1372                 for (int ndx = 0; ndx < m_numDrawCmds; ++ndx)
1373                 {
1374                         const deUint32                  firstTri = ndx * numDrawCallTris;
1375                         DrawElementsCommand             data;
1376
1377                         data.count                              = numDrawCallTris*3;
1378                         data.primCount                  = 1;
1379                         data.firstIndex                 = firstTri*3;
1380                         data.baseVertex                 = 0;
1381                         data.reservedMustBeZero = 0;
1382
1383                         cmds.push_back(data);
1384                 }
1385
1386                 DE_ASSERT((int)(sizeof(DrawElementsCommand)*cmds.size()) == m_numDrawCmds * m_commandSize);
1387
1388                 gl.bindBuffer(GL_DRAW_INDIRECT_BUFFER, m_cmdBufferID);
1389                 gl.bufferData(GL_DRAW_INDIRECT_BUFFER, (glw::GLsizeiptr)(sizeof(DrawElementsCommand)*cmds.size()), &cmds[0], GL_STATIC_DRAW);
1390         }
1391         else
1392                 DE_ASSERT(false);
1393
1394         glu::checkError(gl.getError(), "create draw command", __FILE__, __LINE__);
1395 }
1396
1397 void ComputeShaderGeneratedCase::createDrawData (void)
1398 {
1399         const tcu::Vec4                 yellow  (1.0f, 1.0f, 0.0f, 1.0f);
1400         const tcu::Vec4                 green   (0.0f, 1.0f, 0.0f, 1.0f);
1401         const glw::Functions&   gl              = m_context.getRenderContext().getFunctions();
1402
1403         if (m_drawMethod == DRAWMETHOD_DRAWARRAYS)
1404         {
1405                 // Store elements in the order they are drawn. Interleave color.
1406                 std::vector<tcu::Vec4> buffer(m_gridSize*m_gridSize*6*2);
1407
1408                 DE_ASSERT(buffer.size() == calcDrawBufferSize());
1409
1410                 for (int y = 0; y < m_gridSize; ++y)
1411                 for (int x = 0; x < m_gridSize; ++x)
1412                 {
1413                         const float                     posX            = ((float)x / (float)m_gridSize) * 2.0f - 1.0f;
1414                         const float                     posY            = ((float)y / (float)m_gridSize) * 2.0f - 1.0f;
1415                         const float                     cellSize        = 2.0f / (float)m_gridSize;
1416                         const tcu::Vec4&        color           = ((x + y)%2) ? (yellow) : (green);
1417
1418                         buffer[((y * m_gridSize + x) * 6 + 0) * 2 + 0] = tcu::Vec4(posX,                        posY,                           0.0f, 1.0f);
1419                         buffer[((y * m_gridSize + x) * 6 + 1) * 2 + 0] = tcu::Vec4(posX + cellSize,     posY,                           0.0f, 1.0f);
1420                         buffer[((y * m_gridSize + x) * 6 + 2) * 2 + 0] = tcu::Vec4(posX + cellSize,     posY + cellSize,        0.0f, 1.0f);
1421                         buffer[((y * m_gridSize + x) * 6 + 3) * 2 + 0] = tcu::Vec4(posX,                        posY,                           0.0f, 1.0f);
1422                         buffer[((y * m_gridSize + x) * 6 + 4) * 2 + 0] = tcu::Vec4(posX + cellSize, posY + cellSize,    0.0f, 1.0f);
1423                         buffer[((y * m_gridSize + x) * 6 + 5) * 2 + 0] = tcu::Vec4(posX,                        posY + cellSize,        0.0f, 1.0f);
1424
1425                         buffer[((y * m_gridSize + x) * 6 + 0) * 2 + 1] = color;
1426                         buffer[((y * m_gridSize + x) * 6 + 1) * 2 + 1] = color;
1427                         buffer[((y * m_gridSize + x) * 6 + 2) * 2 + 1] = color;
1428                         buffer[((y * m_gridSize + x) * 6 + 3) * 2 + 1] = color;
1429                         buffer[((y * m_gridSize + x) * 6 + 4) * 2 + 1] = color;
1430                         buffer[((y * m_gridSize + x) * 6 + 5) * 2 + 1] = color;
1431                 }
1432
1433                 gl.bindBuffer(GL_ARRAY_BUFFER, m_dataBufferID);
1434                 gl.bufferData(GL_ARRAY_BUFFER, (int)(buffer.size() * sizeof(tcu::Vec4)), buffer[0].getPtr(), GL_STATIC_DRAW);
1435         }
1436         else if (m_drawMethod == DRAWMETHOD_DRAWELEMENTS)
1437         {
1438                 // Elements are indexed by index buffer. Interleave color. Two vertices per position since 2 colors
1439
1440                 std::vector<tcu::Vec4> buffer((m_gridSize+1)*(m_gridSize+1)*4);
1441
1442                 DE_ASSERT(buffer.size() == calcDrawBufferSize());
1443
1444                 for (int y = 0; y < m_gridSize+1; ++y)
1445                 for (int x = 0; x < m_gridSize+1; ++x)
1446                 {
1447                         const float                     posX            = ((float)x / (float)m_gridSize) * 2.0f - 1.0f;
1448                         const float                     posY            = ((float)y / (float)m_gridSize) * 2.0f - 1.0f;
1449
1450                         buffer[(y * (m_gridSize+1) + x) * 4 + 0] = tcu::Vec4(posX, posY, 0.0f, 1.0f);
1451                         buffer[(y * (m_gridSize+1) + x) * 4 + 1] = green;
1452                         buffer[(y * (m_gridSize+1) + x) * 4 + 2] = tcu::Vec4(posX, posY, 0.0f, 1.0f);
1453                         buffer[(y * (m_gridSize+1) + x) * 4 + 3] = yellow;
1454                 }
1455
1456                 gl.bindBuffer(GL_ARRAY_BUFFER, m_dataBufferID);
1457                 gl.bufferData(GL_ARRAY_BUFFER, (int)(buffer.size() * sizeof(tcu::Vec4)), buffer[0].getPtr(), GL_STATIC_DRAW);
1458         }
1459         else
1460                 DE_ASSERT(false);
1461
1462         glu::checkError(gl.getError(), "", __FILE__, __LINE__);
1463 }
1464
1465 void ComputeShaderGeneratedCase::createDrawIndices (void)
1466 {
1467         DE_ASSERT(m_drawMethod == DRAWMETHOD_DRAWELEMENTS);
1468
1469         const glw::Functions&   gl              = m_context.getRenderContext().getFunctions();
1470         std::vector<deUint32>   buffer  (m_gridSize*m_gridSize*6);
1471
1472         DE_ASSERT(buffer.size() == calcIndexBufferSize());
1473
1474         for (int y = 0; y < m_gridSize; ++y)
1475         for (int x = 0; x < m_gridSize; ++x)
1476         {
1477                 const int color = ((x + y)%2);
1478
1479                 buffer[(y * m_gridSize + x) * 6 + 0] = ((y+0) * (m_gridSize+1) + (x+0)) * 2 + color;
1480                 buffer[(y * m_gridSize + x) * 6 + 1] = ((y+1) * (m_gridSize+1) + (x+0)) * 2 + color;
1481                 buffer[(y * m_gridSize + x) * 6 + 2] = ((y+1) * (m_gridSize+1) + (x+1)) * 2 + color;
1482                 buffer[(y * m_gridSize + x) * 6 + 3] = ((y+0) * (m_gridSize+1) + (x+0)) * 2 + color;
1483                 buffer[(y * m_gridSize + x) * 6 + 4] = ((y+1) * (m_gridSize+1) + (x+1)) * 2 + color;
1484                 buffer[(y * m_gridSize + x) * 6 + 5] = ((y+0) * (m_gridSize+1) + (x+1)) * 2 + color;
1485         }
1486
1487         gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indexBufferID);
1488         gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, (int)(buffer.size() * sizeof(deUint32)), &buffer[0], GL_STATIC_DRAW);
1489         glu::checkError(gl.getError(), "", __FILE__, __LINE__);
1490 }
1491
1492 void ComputeShaderGeneratedCase::renderTo (tcu::Surface& dst)
1493 {
1494         const glw::Functions&   gl                      = m_context.getRenderContext().getFunctions();
1495         const deInt32                   positionLoc = gl.getAttribLocation(m_shaderProgram->getProgram(), "a_position");
1496         const deInt32                   colorLoc        = gl.getAttribLocation(m_shaderProgram->getProgram(), "a_color");
1497         deUint32                                vaoID           = 0;
1498
1499         gl.genVertexArrays(1, &vaoID);
1500         gl.bindVertexArray(vaoID);
1501
1502         // Setup buffers
1503
1504         gl.bindBuffer(GL_ARRAY_BUFFER, m_dataBufferID);
1505         gl.vertexAttribPointer(positionLoc, 4, GL_FLOAT, GL_FALSE, 8 * (int)sizeof(float), DE_NULL);
1506         gl.vertexAttribPointer(colorLoc,    4, GL_FLOAT, GL_FALSE, 8 * (int)sizeof(float), ((const deUint8*)DE_NULL) + 4*sizeof(float));
1507         gl.enableVertexAttribArray(positionLoc);
1508         gl.enableVertexAttribArray(colorLoc);
1509
1510         DE_ASSERT(positionLoc != -1);
1511         DE_ASSERT(colorLoc != -1);
1512
1513         if (m_drawMethod == DRAWMETHOD_DRAWELEMENTS)
1514                 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indexBufferID);
1515
1516         gl.bindBuffer(GL_DRAW_INDIRECT_BUFFER, m_cmdBufferID);
1517
1518         // draw
1519
1520         gl.clearColor(0, 0, 0, 1);
1521         gl.clear(GL_COLOR_BUFFER_BIT);
1522         gl.viewport(0, 0, dst.getWidth(), dst.getHeight());
1523
1524         gl.useProgram(m_shaderProgram->getProgram());
1525         for (int drawCmdNdx = 0; drawCmdNdx < m_numDrawCmds; ++drawCmdNdx)
1526         {
1527                 const void* offset = ((deUint8*)DE_NULL) + drawCmdNdx*m_commandSize;
1528
1529                 if (m_drawMethod == DRAWMETHOD_DRAWELEMENTS)
1530                         gl.drawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_INT, offset);
1531                 else if (m_drawMethod == DRAWMETHOD_DRAWARRAYS)
1532                         gl.drawArraysIndirect(GL_TRIANGLES, offset);
1533                 else
1534                         DE_ASSERT(DE_FALSE);
1535         }
1536         gl.useProgram(0);
1537
1538         // free
1539
1540         gl.deleteVertexArrays(1, &vaoID);
1541         glu::checkError(gl.getError(), "", __FILE__, __LINE__);
1542
1543         gl.finish();
1544         glu::checkError(gl.getError(), "", __FILE__, __LINE__);
1545
1546         glu::readPixels(m_context.getRenderContext(), 0, 0, dst.getAccess());
1547         glu::checkError(gl.getError(), "", __FILE__, __LINE__);
1548 }
1549
1550 deUint32 ComputeShaderGeneratedCase::calcDrawBufferSize (void) const
1551 {
1552         // returns size in "vec4"s
1553         if (m_drawMethod == DRAWMETHOD_DRAWARRAYS)
1554                 return m_gridSize*m_gridSize*6*2;
1555         else if (m_drawMethod == DRAWMETHOD_DRAWELEMENTS)
1556                 return (m_gridSize+1)*(m_gridSize+1)*4;
1557         else
1558                 DE_ASSERT(DE_FALSE);
1559
1560         return 0;
1561 }
1562
1563 deUint32 ComputeShaderGeneratedCase::calcIndexBufferSize (void) const
1564 {
1565         if (m_drawMethod == DRAWMETHOD_DRAWELEMENTS)
1566                 return m_gridSize*m_gridSize*6;
1567         else
1568                 return 0;
1569 }
1570
1571 class ComputeShaderGeneratedCombinedCase : public ComputeShaderGeneratedCase
1572 {
1573 public:
1574                                                 ComputeShaderGeneratedCombinedCase      (Context& context, const char* name, const char* desc, DrawMethod method, bool computeCmd, bool computeData, bool computeIndices, int gridSize, int numDrawCalls);
1575                                                 ~ComputeShaderGeneratedCombinedCase     (void);
1576
1577         void                            init                                                            (void);
1578         void                            deinit                                                          (void);
1579
1580 private:
1581         void                            runComputeShader                                        (void);
1582
1583         glu::ShaderProgram*     m_computeProgram;
1584 };
1585
1586 ComputeShaderGeneratedCombinedCase::ComputeShaderGeneratedCombinedCase (Context& context, const char* name, const char* desc, DrawMethod method, bool computeCmd, bool computeData, bool computeIndices, int gridSize, int numDrawCalls)
1587         : ComputeShaderGeneratedCase(context, name, desc, method, computeCmd, computeData, computeIndices, gridSize, numDrawCalls)
1588         , m_computeProgram                      (DE_NULL)
1589 {
1590 }
1591
1592 ComputeShaderGeneratedCombinedCase::~ComputeShaderGeneratedCombinedCase (void)
1593 {
1594         deinit();
1595 }
1596
1597 void ComputeShaderGeneratedCombinedCase::init (void)
1598 {
1599         // generate compute shader
1600
1601         m_computeProgram = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(genComputeSource(m_computeCmd, m_computeData, m_computeIndices)));
1602         m_testCtx.getLog() << *m_computeProgram;
1603
1604         if (!m_computeProgram->isOk())
1605                 throw tcu::TestError("Failed to compile compute shader.");
1606
1607         // init parent
1608         ComputeShaderGeneratedCase::init();
1609 }
1610
1611 void ComputeShaderGeneratedCombinedCase::deinit (void)
1612 {
1613         // deinit parent
1614         ComputeShaderGeneratedCase::deinit();
1615
1616         if (m_computeProgram)
1617         {
1618                 delete m_computeProgram;
1619                 m_computeProgram = DE_NULL;
1620         }
1621 }
1622
1623 void ComputeShaderGeneratedCombinedCase::runComputeShader (void)
1624 {
1625         const glw::Functions&   gl                                                                      = m_context.getRenderContext().getFunctions();
1626         const bool                              indexed                                                         = (m_drawMethod == DRAWMETHOD_DRAWELEMENTS);
1627         const tcu::IVec3                nullSize                                                        (0, 0, 0);
1628         const tcu::IVec3                commandDispatchSize                                     = (m_computeCmd)                                ? (tcu::IVec3(m_numDrawCmds, 1, 1))                             : (nullSize);
1629         const tcu::IVec3                drawElementsDataBufferDispatchSize      = (m_computeData)                               ? (tcu::IVec3(m_gridSize+1, m_gridSize+1, 1))   : (nullSize);
1630         const tcu::IVec3                drawArraysDataBufferDispatchSize        = (m_computeData)                               ? (tcu::IVec3(m_gridSize,   m_gridSize,   1))   : (nullSize);
1631         const tcu::IVec3                indexBufferDispatchSize                         = (m_computeIndices && indexed) ? (tcu::IVec3(m_gridSize,   m_gridSize,   1))   : (nullSize);
1632
1633         const tcu::IVec3                dataBufferDispatchSize                          = (m_drawMethod == DRAWMETHOD_DRAWELEMENTS) ? (drawElementsDataBufferDispatchSize) : (drawArraysDataBufferDispatchSize);
1634         const tcu::IVec3                dispatchSize                                            = tcu::max(tcu::max(commandDispatchSize, dataBufferDispatchSize), indexBufferDispatchSize);
1635
1636         gl.useProgram(m_computeProgram->getProgram());
1637         glu::checkError(gl.getError(), "use compute shader", __FILE__, __LINE__);
1638
1639         // setup buffers
1640
1641         if (m_computeCmd)
1642         {
1643                 const int                       bindingPoint    = 0;
1644                 const int                       bufferSize              = m_commandSize * m_numDrawCmds;
1645
1646                 m_testCtx.getLog() << tcu::TestLog::Message << "Binding command buffer to binding point " << bindingPoint << tcu::TestLog::EndMessage;
1647                 gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, bindingPoint, m_cmdBufferID);
1648
1649                 m_testCtx.getLog() << tcu::TestLog::Message << "Allocating memory for command buffer, size " << sizeToString(bufferSize) << "." << tcu::TestLog::EndMessage;
1650                 gl.bufferData(GL_SHADER_STORAGE_BUFFER, bufferSize, DE_NULL, GL_DYNAMIC_DRAW);
1651         }
1652
1653         if (m_computeData)
1654         {
1655                 const int                       bindingPoint    = (m_computeCmd) ? (1) : (0);
1656                 const int                       bufferSize              = (int)(calcDrawBufferSize()*sizeof(tcu::Vec4));
1657
1658                 m_testCtx.getLog() << tcu::TestLog::Message << "Binding data buffer to binding point " << bindingPoint << tcu::TestLog::EndMessage;
1659                 gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, bindingPoint, m_dataBufferID);
1660
1661                 m_testCtx.getLog() << tcu::TestLog::Message << "Allocating memory for data buffer, size " << sizeToString(bufferSize) << "." << tcu::TestLog::EndMessage;
1662                 gl.bufferData(GL_SHADER_STORAGE_BUFFER, bufferSize, DE_NULL, GL_DYNAMIC_DRAW);
1663         }
1664
1665         if (m_computeIndices)
1666         {
1667                 const int                       bindingPoint    = (m_computeCmd && m_computeData) ? (2) : (m_computeCmd || m_computeData) ? (1) : (0);
1668                 const int                       bufferSize              = (int)(calcIndexBufferSize()*sizeof(deUint32));
1669
1670                 m_testCtx.getLog() << tcu::TestLog::Message << "Binding index buffer to binding point " << bindingPoint << tcu::TestLog::EndMessage;
1671                 gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, bindingPoint, m_indexBufferID);
1672
1673                 m_testCtx.getLog() << tcu::TestLog::Message << "Allocating memory for index buffer, size " << sizeToString(bufferSize) << "." << tcu::TestLog::EndMessage;
1674                 gl.bufferData(GL_SHADER_STORAGE_BUFFER, bufferSize, DE_NULL, GL_DYNAMIC_DRAW);
1675         }
1676
1677         glu::checkError(gl.getError(), "setup buffers", __FILE__, __LINE__);
1678
1679         // calculate
1680
1681         m_testCtx.getLog() << tcu::TestLog::Message << "Dispatching compute, size = " << dispatchSize << tcu::TestLog::EndMessage;
1682         gl.dispatchCompute(dispatchSize.x(), dispatchSize.y(), dispatchSize.z());
1683
1684         glu::checkError(gl.getError(), "calculate", __FILE__, __LINE__);
1685 }
1686
1687 class ComputeShaderGeneratedSeparateCase : public ComputeShaderGeneratedCase
1688 {
1689 public:
1690                                                 ComputeShaderGeneratedSeparateCase      (Context& context, const char* name, const char* desc, DrawMethod method, bool computeCmd, bool computeData, bool computeIndices, int gridSize, int numDrawCalls);
1691                                                 ~ComputeShaderGeneratedSeparateCase     (void);
1692
1693         void                            init                                                            (void);
1694         void                            deinit                                                          (void);
1695
1696 private:
1697         std::string                     genCmdComputeSource                                     (void);
1698         std::string                     genDataComputeSource                            (void);
1699         std::string                     genIndexComputeSource                           (void);
1700         void                            runComputeShader                                        (void);
1701
1702         glu::ShaderProgram*     m_computeCmdProgram;
1703         glu::ShaderProgram*     m_computeDataProgram;
1704         glu::ShaderProgram*     m_computeIndicesProgram;
1705 };
1706
1707 ComputeShaderGeneratedSeparateCase::ComputeShaderGeneratedSeparateCase (Context& context, const char* name, const char* desc, DrawMethod method, bool computeCmd, bool computeData, bool computeIndices, int gridSize, int numDrawCalls)
1708         : ComputeShaderGeneratedCase    (context, name, desc, method, computeCmd, computeData, computeIndices, gridSize, numDrawCalls)
1709         , m_computeCmdProgram                   (DE_NULL)
1710         , m_computeDataProgram                  (DE_NULL)
1711         , m_computeIndicesProgram               (DE_NULL)
1712 {
1713 }
1714
1715 ComputeShaderGeneratedSeparateCase::~ComputeShaderGeneratedSeparateCase (void)
1716 {
1717         deinit();
1718 }
1719
1720 void ComputeShaderGeneratedSeparateCase::init (void)
1721 {
1722         // generate cmd compute shader
1723
1724         if (m_computeCmd)
1725         {
1726                 m_computeCmdProgram = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(genCmdComputeSource()));
1727                 m_testCtx.getLog() << *m_computeCmdProgram;
1728
1729                 if (!m_computeCmdProgram->isOk())
1730                         throw tcu::TestError("Failed to compile command compute shader.");
1731         }
1732
1733         // generate data compute shader
1734
1735         if (m_computeData)
1736         {
1737                 m_computeDataProgram = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(genDataComputeSource()));
1738                 m_testCtx.getLog() << *m_computeDataProgram;
1739
1740                 if (!m_computeDataProgram->isOk())
1741                         throw tcu::TestError("Failed to compile data compute shader.");
1742         }
1743
1744         // generate index compute shader
1745
1746         if (m_computeIndices)
1747         {
1748                 m_computeIndicesProgram = new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() << glu::ComputeSource(genIndexComputeSource()));
1749                 m_testCtx.getLog() << *m_computeIndicesProgram;
1750
1751                 if (!m_computeIndicesProgram->isOk())
1752                         throw tcu::TestError("Failed to compile data compute shader.");
1753         }
1754
1755         // init parent
1756         ComputeShaderGeneratedCase::init();
1757 }
1758
1759 void ComputeShaderGeneratedSeparateCase::deinit (void)
1760 {
1761         // deinit parent
1762         ComputeShaderGeneratedCase::deinit();
1763
1764         if (m_computeCmdProgram)
1765         {
1766                 delete m_computeCmdProgram;
1767                 m_computeCmdProgram = DE_NULL;
1768         }
1769         if (m_computeDataProgram)
1770         {
1771                 delete m_computeDataProgram;
1772                 m_computeDataProgram = DE_NULL;
1773         }
1774         if (m_computeIndicesProgram)
1775         {
1776                 delete m_computeIndicesProgram;
1777                 m_computeIndicesProgram = DE_NULL;
1778         }
1779 }
1780
1781 std::string ComputeShaderGeneratedSeparateCase::genCmdComputeSource (void)
1782 {
1783         return ComputeShaderGeneratedCase::genComputeSource(true, false, false);
1784 }
1785
1786 std::string ComputeShaderGeneratedSeparateCase::genDataComputeSource (void)
1787 {
1788         return ComputeShaderGeneratedCase::genComputeSource(false, true, false);
1789 }
1790
1791 std::string ComputeShaderGeneratedSeparateCase::genIndexComputeSource (void)
1792 {
1793         return ComputeShaderGeneratedCase::genComputeSource(false, false, true);
1794 }
1795
1796 void ComputeShaderGeneratedSeparateCase::runComputeShader (void)
1797 {
1798         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1799
1800         // Compute command
1801
1802         if (m_computeCmd)
1803         {
1804                 const int                               bindingPoint                    = 0;
1805                 const tcu::IVec3                commandDispatchSize             (m_numDrawCmds, 1, 1);
1806                 const int                               bufferSize                              = m_commandSize * m_numDrawCmds;
1807
1808                 gl.useProgram(m_computeCmdProgram->getProgram());
1809
1810                 // setup buffers
1811
1812                 m_testCtx.getLog() << tcu::TestLog::Message << "Binding command buffer to binding point " << bindingPoint << tcu::TestLog::EndMessage;
1813                 gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, bindingPoint, m_cmdBufferID);
1814
1815                 m_testCtx.getLog() << tcu::TestLog::Message << "Allocating memory for command buffer, size " << sizeToString(bufferSize) << "." << tcu::TestLog::EndMessage;
1816                 gl.bufferData(GL_SHADER_STORAGE_BUFFER, bufferSize, DE_NULL, GL_DYNAMIC_DRAW);
1817
1818                 // calculate
1819
1820                 m_testCtx.getLog() << tcu::TestLog::Message << "Dispatching command compute, size = " << commandDispatchSize << tcu::TestLog::EndMessage;
1821                 gl.dispatchCompute(commandDispatchSize.x(), commandDispatchSize.y(), commandDispatchSize.z());
1822
1823                 glu::checkError(gl.getError(), "calculate cmd", __FILE__, __LINE__);
1824         }
1825
1826         // Compute data
1827
1828         if (m_computeData)
1829         {
1830                 const int                               bindingPoint                                            = 0;
1831                 const tcu::IVec3                drawElementsDataBufferDispatchSize      (m_gridSize+1, m_gridSize+1, 1);
1832                 const tcu::IVec3                drawArraysDataBufferDispatchSize        (m_gridSize,   m_gridSize,   1);
1833                 const tcu::IVec3                dataBufferDispatchSize                          = (m_drawMethod == DRAWMETHOD_DRAWELEMENTS) ? (drawElementsDataBufferDispatchSize) : (drawArraysDataBufferDispatchSize);
1834                 const int                               bufferSize                                                      = (int)(calcDrawBufferSize()*sizeof(tcu::Vec4));
1835
1836                 gl.useProgram(m_computeDataProgram->getProgram());
1837
1838                 // setup buffers
1839
1840                 m_testCtx.getLog() << tcu::TestLog::Message << "Binding data buffer to binding point " << bindingPoint << tcu::TestLog::EndMessage;
1841                 gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, bindingPoint, m_dataBufferID);
1842
1843                 m_testCtx.getLog() << tcu::TestLog::Message << "Allocating memory for data buffer, size " << sizeToString(bufferSize) << "." << tcu::TestLog::EndMessage;
1844                 gl.bufferData(GL_SHADER_STORAGE_BUFFER, bufferSize, DE_NULL, GL_DYNAMIC_DRAW);
1845
1846                 // calculate
1847
1848                 m_testCtx.getLog() << tcu::TestLog::Message << "Dispatching data compute, size = " << dataBufferDispatchSize << tcu::TestLog::EndMessage;
1849                 gl.dispatchCompute(dataBufferDispatchSize.x(), dataBufferDispatchSize.y(), dataBufferDispatchSize.z());
1850
1851                 glu::checkError(gl.getError(), "calculate data", __FILE__, __LINE__);
1852         }
1853
1854         // Compute indices
1855
1856         if (m_computeIndices)
1857         {
1858                 const int                               bindingPoint                            = 0;
1859                 const tcu::IVec3                indexBufferDispatchSize         (m_gridSize, m_gridSize, 1);
1860                 const int                               bufferSize                                      = (int)(calcIndexBufferSize()*sizeof(deUint32));
1861
1862                 DE_ASSERT(m_drawMethod == DRAWMETHOD_DRAWELEMENTS);
1863
1864                 gl.useProgram(m_computeIndicesProgram->getProgram());
1865
1866                 // setup buffers
1867
1868                 m_testCtx.getLog() << tcu::TestLog::Message << "Binding index buffer to binding point " << bindingPoint << tcu::TestLog::EndMessage;
1869                 gl.bindBufferBase(GL_SHADER_STORAGE_BUFFER, bindingPoint, m_indexBufferID);
1870
1871                 m_testCtx.getLog() << tcu::TestLog::Message << "Allocating memory for index buffer, size " << sizeToString(bufferSize) << "." << tcu::TestLog::EndMessage;
1872                 gl.bufferData(GL_SHADER_STORAGE_BUFFER, bufferSize, DE_NULL, GL_DYNAMIC_DRAW);
1873
1874                 // calculate
1875
1876                 m_testCtx.getLog() << tcu::TestLog::Message << "Dispatching index compute, size = " << indexBufferDispatchSize << tcu::TestLog::EndMessage;
1877                 gl.dispatchCompute(indexBufferDispatchSize.x(), indexBufferDispatchSize.y(), indexBufferDispatchSize.z());
1878
1879                 glu::checkError(gl.getError(), "calculate indices", __FILE__, __LINE__);
1880         }
1881
1882         glu::checkError(gl.getError(), "post dispatch", __FILE__, __LINE__);
1883 }
1884
1885 class ComputeShaderGeneratedGroup : public TestCaseGroup
1886 {
1887 public:
1888                         ComputeShaderGeneratedGroup             (Context& context, const char* name, const char* descr);
1889                         ~ComputeShaderGeneratedGroup    (void);
1890
1891         void    init                                                    (void);
1892 };
1893
1894 ComputeShaderGeneratedGroup::ComputeShaderGeneratedGroup (Context& context, const char* name, const char* descr)
1895         : TestCaseGroup (context, name, descr)
1896 {
1897 }
1898
1899 ComputeShaderGeneratedGroup::~ComputeShaderGeneratedGroup (void)
1900 {
1901 }
1902
1903 void ComputeShaderGeneratedGroup::init (void)
1904 {
1905         const int                                       gridSize                = 8;
1906         tcu::TestCaseGroup* const       separateGroup   = new tcu::TestCaseGroup(m_testCtx, "separate", "Use separate compute shaders for each buffer");
1907         tcu::TestCaseGroup* const       combinedGroup   = new tcu::TestCaseGroup(m_testCtx, "combined", "Use combined compute shader for all buffers");
1908         tcu::TestCaseGroup* const       largeGroup              = new tcu::TestCaseGroup(m_testCtx, "large",   "Draw shapes with large buffers");
1909
1910         this->addChild(separateGroup);
1911         this->addChild(combinedGroup);
1912         this->addChild(largeGroup);
1913
1914         // .separate
1915         {
1916                 separateGroup->addChild(new ComputeShaderGeneratedSeparateCase(m_context, "drawarrays_compute_cmd",                                                     "Command from compute shader",                                          ComputeShaderGeneratedCase::DRAWMETHOD_DRAWARRAYS,              true,   false,  false,  gridSize,       1));
1917                 separateGroup->addChild(new ComputeShaderGeneratedSeparateCase(m_context, "drawarrays_compute_data",                                            "Data from compute shader",                                                     ComputeShaderGeneratedCase::DRAWMETHOD_DRAWARRAYS,              false,  true,   false,  gridSize,       1));
1918                 separateGroup->addChild(new ComputeShaderGeneratedSeparateCase(m_context, "drawarrays_compute_cmd_and_data",                            "Command and data from compute shader",                         ComputeShaderGeneratedCase::DRAWMETHOD_DRAWARRAYS,              true,   true,   false,  gridSize,       1));
1919
1920                 separateGroup->addChild(new ComputeShaderGeneratedSeparateCase(m_context, "drawelements_compute_cmd",                                           "Command from compute shader",                                          ComputeShaderGeneratedCase::DRAWMETHOD_DRAWELEMENTS,    true,   false,  false,  gridSize,       1));
1921                 separateGroup->addChild(new ComputeShaderGeneratedSeparateCase(m_context, "drawelements_compute_data",                                          "Data from compute shader",                                                     ComputeShaderGeneratedCase::DRAWMETHOD_DRAWELEMENTS,    false,  true,   false,  gridSize,       1));
1922                 separateGroup->addChild(new ComputeShaderGeneratedSeparateCase(m_context, "drawelements_compute_indices",                                       "Indices from compute shader",                                          ComputeShaderGeneratedCase::DRAWMETHOD_DRAWELEMENTS,    false,  false,  true,   gridSize,       1));
1923                 separateGroup->addChild(new ComputeShaderGeneratedSeparateCase(m_context, "drawelements_compute_cmd_and_data",                          "Command and data from compute shader",                         ComputeShaderGeneratedCase::DRAWMETHOD_DRAWELEMENTS,    true,   true,   false,  gridSize,       1));
1924                 separateGroup->addChild(new ComputeShaderGeneratedSeparateCase(m_context, "drawelements_compute_cmd_and_indices",                       "Command and indices from compute shader",                      ComputeShaderGeneratedCase::DRAWMETHOD_DRAWELEMENTS,    true,   false,  true,   gridSize,       1));
1925                 separateGroup->addChild(new ComputeShaderGeneratedSeparateCase(m_context, "drawelements_compute_data_and_indices",                      "Data and indices from compute shader",                         ComputeShaderGeneratedCase::DRAWMETHOD_DRAWELEMENTS,    false,  true,   true,   gridSize,       1));
1926                 separateGroup->addChild(new ComputeShaderGeneratedSeparateCase(m_context, "drawelements_compute_cmd_and_data_and_indices",      "Command, data and indices from compute shader",        ComputeShaderGeneratedCase::DRAWMETHOD_DRAWELEMENTS,    true,   true,   true,   gridSize,       1));
1927         }
1928
1929         // .combined
1930         {
1931                 combinedGroup->addChild(new ComputeShaderGeneratedCombinedCase(m_context, "drawarrays_compute_cmd_and_data",                            "Command and data from compute shader",                         ComputeShaderGeneratedCase::DRAWMETHOD_DRAWARRAYS,              true,   true,   false,  gridSize,       1));
1932                 combinedGroup->addChild(new ComputeShaderGeneratedCombinedCase(m_context, "drawelements_compute_cmd_and_data",                          "Command and data from compute shader",                         ComputeShaderGeneratedCase::DRAWMETHOD_DRAWELEMENTS,    true,   true,   false,  gridSize,       1));
1933                 combinedGroup->addChild(new ComputeShaderGeneratedCombinedCase(m_context, "drawelements_compute_cmd_and_indices",                       "Command and indices from compute shader",                      ComputeShaderGeneratedCase::DRAWMETHOD_DRAWELEMENTS,    true,   false,  true,   gridSize,       1));
1934                 combinedGroup->addChild(new ComputeShaderGeneratedCombinedCase(m_context, "drawelements_compute_data_and_indices",                      "Data and indices from compute shader",                         ComputeShaderGeneratedCase::DRAWMETHOD_DRAWELEMENTS,    false,  true,   true,   gridSize,       1));
1935                 combinedGroup->addChild(new ComputeShaderGeneratedCombinedCase(m_context, "drawelements_compute_cmd_and_data_and_indices",      "Command, data and indices from compute shader",        ComputeShaderGeneratedCase::DRAWMETHOD_DRAWELEMENTS,    true,   true,   true,   gridSize,       1));
1936         }
1937
1938         // .large
1939         {
1940                 struct TestSpec
1941                 {
1942                         int gridSize;
1943                         int numDrawCommands;
1944                 };
1945                 struct TestMethod
1946                 {
1947                         ComputeShaderGeneratedCase::DrawMethod method;
1948                         bool                                   separateCompute;
1949                 };
1950
1951                 static const TestSpec specs[] =
1952                 {
1953                         { 100,  1 },            // !< drawArrays array size ~ 1.9 MB
1954                         { 200,  1 },            // !< drawArrays array size ~ 7.7 MB
1955                         { 500,  1 },            // !< drawArrays array size ~ 48 MB
1956                         { 1000, 1 },            // !< drawArrays array size ~ 192 MB
1957                         { 1200, 1 },            // !< drawArrays array size ~ 277 MB
1958                         { 1500, 1 },            // !< drawArrays array size ~ 430 MB
1959
1960                         { 100,  8 },            // !< drawArrays array size ~ 1.9 MB
1961                         { 200,  8 },            // !< drawArrays array size ~ 7.7 MB
1962                         { 500,  8 },            // !< drawArrays array size ~ 48 MB
1963                         { 1000, 8 },            // !< drawArrays array size ~ 192 MB
1964                         { 1200, 8 },            // !< drawArrays array size ~ 277 MB
1965                         { 1500, 8 },            // !< drawArrays array size ~ 430 MB
1966
1967                         { 100,  200  },         // !< 50 cells per draw call
1968                         { 200,  800  },         // !< 50 cells per draw call
1969                         { 500,  2500 },         // !< 100 cells per draw call
1970                         { 1000, 5000 },         // !< 250 cells per draw call
1971                 };
1972                 static const TestMethod methods[] =
1973                 {
1974                         { ComputeShaderGeneratedCase::DRAWMETHOD_DRAWARRAYS,    true    },
1975                         { ComputeShaderGeneratedCase::DRAWMETHOD_DRAWARRAYS,    false   },
1976                         { ComputeShaderGeneratedCase::DRAWMETHOD_DRAWELEMENTS,  true    },
1977                         { ComputeShaderGeneratedCase::DRAWMETHOD_DRAWELEMENTS,  false   },
1978                 };
1979
1980                 for (int methodNdx = 0; methodNdx < DE_LENGTH_OF_ARRAY(methods); ++methodNdx)
1981                 for (int specNdx = 0; specNdx < DE_LENGTH_OF_ARRAY(specs); ++specNdx)
1982                 {
1983                         const std::string name = std::string("")
1984                                                                         + ((methods[methodNdx].method == ComputeShaderGeneratedCase::DRAWMETHOD_DRAWARRAYS) ? ("drawarrays") : ("drawelements"))
1985                                                                         + ((methods[methodNdx].separateCompute) ? ("_separate") : ("_combined"))
1986                                                                         + "_grid_" + de::toString(specs[specNdx].gridSize) + "x" + de::toString(specs[specNdx].gridSize)
1987                                                                         + "_drawcount_" + de::toString(specs[specNdx].numDrawCommands);
1988
1989                         const std::string desc = std::string("Draw grid with ")
1990                                                                         + ((methods[methodNdx].method == ComputeShaderGeneratedCase::DRAWMETHOD_DRAWARRAYS) ? ("drawarrays indirect") : ("drawelements indirect"))
1991                                                                         + " calculating buffers in " + ((methods[methodNdx].separateCompute) ? ("separate") : ("combined")) + " compute shader."
1992                                                                         + " Grid size is " + de::toString(specs[specNdx].gridSize) + "x" + de::toString(specs[specNdx].gridSize)
1993                                                                         + ", draw count is "  + de::toString(specs[specNdx].numDrawCommands);
1994
1995                         const bool computeIndices = (methods[methodNdx].method == ComputeShaderGeneratedCase::DRAWMETHOD_DRAWELEMENTS);
1996
1997                         if (methods[methodNdx].separateCompute)
1998                                 largeGroup->addChild(new ComputeShaderGeneratedSeparateCase(m_context, name.c_str(), desc.c_str(), methods[methodNdx].method, false, true, computeIndices, specs[specNdx].gridSize, specs[specNdx].numDrawCommands));
1999                         else
2000                                 largeGroup->addChild(new ComputeShaderGeneratedCombinedCase(m_context, name.c_str(), desc.c_str(), methods[methodNdx].method, false, true, computeIndices, specs[specNdx].gridSize, specs[specNdx].numDrawCommands));
2001                 }
2002         }
2003 }
2004
2005 class RandomGroup : public TestCaseGroup
2006 {
2007 public:
2008                         RandomGroup             (Context& context, const char* name, const char* descr);
2009                         ~RandomGroup    (void);
2010
2011         void    init                    (void);
2012 };
2013
2014 template <int SIZE>
2015 struct UniformWeightArray
2016 {
2017         float weights[SIZE];
2018
2019         UniformWeightArray (void)
2020         {
2021                 for (int i=0; i<SIZE; ++i)
2022                         weights[i] = 1.0f;
2023         }
2024 };
2025
2026 RandomGroup::RandomGroup (Context& context, const char* name, const char* descr)
2027         : TestCaseGroup (context, name, descr)
2028 {
2029 }
2030
2031 RandomGroup::~RandomGroup (void)
2032 {
2033 }
2034
2035 void RandomGroup::init (void)
2036 {
2037         const int       numAttempts                             = 100;
2038
2039         const int       attribCounts[]                  = { 1,   2,   5 };
2040         const float     attribWeights[]                 = { 30, 10,   1 };
2041         const int       primitiveCounts[]               = { 1,   5,  64 };
2042         const float     primitiveCountWeights[] = { 20, 10,   1 };
2043         const int       indexOffsets[]                  = { 0,   7,  13 };
2044         const float     indexOffsetWeights[]    = { 20, 20,   1 };
2045         const int       firsts[]                                = { 0,   7,  13 };
2046         const float     firstWeights[]                  = { 20, 20,   1 };
2047
2048         const int       instanceCounts[]                = { 1,   2,  16,  17 };
2049         const float     instanceWeights[]               = { 20, 10,   5,   1 };
2050         const int       indexMins[]                             = { 0,   1,   3,   8 };
2051         const int       indexMaxs[]                             = { 4,   8, 128, 257 };
2052         const float     indexWeights[]                  = { 50, 50,  50,  50 };
2053         const int       offsets[]                               = { 0,   1,   5,  12 };
2054         const float     offsetWeights[]                 = { 50, 10,  10,  10 };
2055         const int       strides[]                               = { 0,   7,  16,  17 };
2056         const float     strideWeights[]                 = { 50, 10,  10,  10 };
2057         const int       instanceDivisors[]              = { 0,   1,   3, 129 };
2058         const float     instanceDivisorWeights[]= { 70, 30,  10,  10 };
2059
2060         const int       indirectOffsets[]               = { 0,   1,   2 };
2061         const float indirectOffsetWeigths[]     = { 2,   1,   1 };
2062         const int       baseVertices[]                  = { 0,   1,  -2,   4,  3 };
2063         const float baseVertexWeigths[]         = { 4,   1,   1,   1,  1 };
2064
2065         gls::DrawTestSpec::Primitive primitives[] =
2066         {
2067                 gls::DrawTestSpec::PRIMITIVE_POINTS,
2068                 gls::DrawTestSpec::PRIMITIVE_TRIANGLES,
2069                 gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN,
2070                 gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP,
2071                 gls::DrawTestSpec::PRIMITIVE_LINES,
2072                 gls::DrawTestSpec::PRIMITIVE_LINE_STRIP,
2073                 gls::DrawTestSpec::PRIMITIVE_LINE_LOOP
2074         };
2075         const UniformWeightArray<DE_LENGTH_OF_ARRAY(primitives)> primitiveWeights;
2076
2077         gls::DrawTestSpec::DrawMethod drawMethods[] =
2078         {
2079                 gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS_INDIRECT,
2080                 gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INDIRECT,
2081         };
2082         const UniformWeightArray<DE_LENGTH_OF_ARRAY(drawMethods)> drawMethodWeights;
2083
2084         gls::DrawTestSpec::IndexType indexTypes[] =
2085         {
2086                 gls::DrawTestSpec::INDEXTYPE_BYTE,
2087                 gls::DrawTestSpec::INDEXTYPE_SHORT,
2088                 gls::DrawTestSpec::INDEXTYPE_INT,
2089         };
2090         const UniformWeightArray<DE_LENGTH_OF_ARRAY(indexTypes)> indexTypeWeights;
2091
2092         gls::DrawTestSpec::InputType inputTypes[] =
2093         {
2094                 gls::DrawTestSpec::INPUTTYPE_FLOAT,
2095                 gls::DrawTestSpec::INPUTTYPE_FIXED,
2096                 gls::DrawTestSpec::INPUTTYPE_BYTE,
2097                 gls::DrawTestSpec::INPUTTYPE_SHORT,
2098                 gls::DrawTestSpec::INPUTTYPE_UNSIGNED_BYTE,
2099                 gls::DrawTestSpec::INPUTTYPE_UNSIGNED_SHORT,
2100                 gls::DrawTestSpec::INPUTTYPE_INT,
2101                 gls::DrawTestSpec::INPUTTYPE_UNSIGNED_INT,
2102                 gls::DrawTestSpec::INPUTTYPE_HALF,
2103                 gls::DrawTestSpec::INPUTTYPE_UNSIGNED_INT_2_10_10_10,
2104                 gls::DrawTestSpec::INPUTTYPE_INT_2_10_10_10,
2105         };
2106         const UniformWeightArray<DE_LENGTH_OF_ARRAY(inputTypes)> inputTypeWeights;
2107
2108         gls::DrawTestSpec::OutputType outputTypes[] =
2109         {
2110                 gls::DrawTestSpec::OUTPUTTYPE_FLOAT,
2111                 gls::DrawTestSpec::OUTPUTTYPE_VEC2,
2112                 gls::DrawTestSpec::OUTPUTTYPE_VEC3,
2113                 gls::DrawTestSpec::OUTPUTTYPE_VEC4,
2114                 gls::DrawTestSpec::OUTPUTTYPE_INT,
2115                 gls::DrawTestSpec::OUTPUTTYPE_UINT,
2116                 gls::DrawTestSpec::OUTPUTTYPE_IVEC2,
2117                 gls::DrawTestSpec::OUTPUTTYPE_IVEC3,
2118                 gls::DrawTestSpec::OUTPUTTYPE_IVEC4,
2119                 gls::DrawTestSpec::OUTPUTTYPE_UVEC2,
2120                 gls::DrawTestSpec::OUTPUTTYPE_UVEC3,
2121                 gls::DrawTestSpec::OUTPUTTYPE_UVEC4,
2122         };
2123         const UniformWeightArray<DE_LENGTH_OF_ARRAY(outputTypes)> outputTypeWeights;
2124
2125         gls::DrawTestSpec::Usage usages[] =
2126         {
2127                 gls::DrawTestSpec::USAGE_DYNAMIC_DRAW,
2128                 gls::DrawTestSpec::USAGE_STATIC_DRAW,
2129                 gls::DrawTestSpec::USAGE_STREAM_DRAW,
2130                 gls::DrawTestSpec::USAGE_STREAM_READ,
2131                 gls::DrawTestSpec::USAGE_STREAM_COPY,
2132                 gls::DrawTestSpec::USAGE_STATIC_READ,
2133                 gls::DrawTestSpec::USAGE_STATIC_COPY,
2134                 gls::DrawTestSpec::USAGE_DYNAMIC_READ,
2135                 gls::DrawTestSpec::USAGE_DYNAMIC_COPY,
2136         };
2137         const UniformWeightArray<DE_LENGTH_OF_ARRAY(usages)> usageWeights;
2138
2139         std::set<deUint32>      insertedHashes;
2140         size_t                          insertedCount = 0;
2141
2142         for (int ndx = 0; ndx < numAttempts; ++ndx)
2143         {
2144                 de::Random random(0xc551393 + ndx); // random does not depend on previous cases
2145
2146                 int                                     attributeCount = random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(attribCounts), DE_ARRAY_END(attribCounts), attribWeights);
2147                 int                                     drawCommandSize;
2148                 gls::DrawTestSpec       spec;
2149
2150                 spec.apiType                            = glu::ApiType::es(3,1);
2151                 spec.primitive                          = random.chooseWeighted<gls::DrawTestSpec::Primitive>   (DE_ARRAY_BEGIN(primitives),            DE_ARRAY_END(primitives),               primitiveWeights.weights);
2152                 spec.primitiveCount                     = random.chooseWeighted<int, const int*, const float*>  (DE_ARRAY_BEGIN(primitiveCounts),       DE_ARRAY_END(primitiveCounts),  primitiveCountWeights);
2153                 spec.drawMethod                         = random.chooseWeighted<gls::DrawTestSpec::DrawMethod>  (DE_ARRAY_BEGIN(drawMethods),           DE_ARRAY_END(drawMethods),              drawMethodWeights.weights);
2154
2155                 if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS_INDIRECT)
2156                         drawCommandSize = sizeof(deUint32[4]);
2157                 else if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INDIRECT)
2158                         drawCommandSize = sizeof(deUint32[5]);
2159                 else
2160                 {
2161                         DE_ASSERT(DE_FALSE);
2162                         return;
2163                 }
2164
2165                 spec.indexType                          = random.chooseWeighted<gls::DrawTestSpec::IndexType>   (DE_ARRAY_BEGIN(indexTypes),            DE_ARRAY_END(indexTypes),               indexTypeWeights.weights);
2166                 spec.indexPointerOffset         = random.chooseWeighted<int, const int*, const float*>  (DE_ARRAY_BEGIN(indexOffsets),          DE_ARRAY_END(indexOffsets),             indexOffsetWeights);
2167                 spec.indexStorage                       = gls::DrawTestSpec::STORAGE_BUFFER;
2168                 spec.first                                      = random.chooseWeighted<int, const int*, const float*>  (DE_ARRAY_BEGIN(firsts),                        DE_ARRAY_END(firsts),                   firstWeights);
2169                 spec.indexMin                           = random.chooseWeighted<int, const int*, const float*>  (DE_ARRAY_BEGIN(indexMins),                     DE_ARRAY_END(indexMins),                indexWeights);
2170                 spec.indexMax                           = random.chooseWeighted<int, const int*, const float*>  (DE_ARRAY_BEGIN(indexMaxs),                     DE_ARRAY_END(indexMaxs),                indexWeights);
2171                 spec.instanceCount                      = random.chooseWeighted<int, const int*, const float*>  (DE_ARRAY_BEGIN(instanceCounts),        DE_ARRAY_END(instanceCounts),   instanceWeights);
2172                 spec.indirectOffset                     = random.chooseWeighted<int, const int*, const float*>  (DE_ARRAY_BEGIN(indirectOffsets),       DE_ARRAY_END(indirectOffsets),  indirectOffsetWeigths) * drawCommandSize;
2173                 spec.baseVertex                         = random.chooseWeighted<int, const int*, const float*>  (DE_ARRAY_BEGIN(baseVertices),          DE_ARRAY_END(baseVertices),             baseVertexWeigths);
2174
2175                 // check spec is legal
2176                 if (!spec.valid())
2177                         continue;
2178
2179                 for (int attrNdx = 0; attrNdx < attributeCount;)
2180                 {
2181                         bool valid;
2182                         gls::DrawTestSpec::AttributeSpec attribSpec;
2183
2184                         attribSpec.inputType                    = random.chooseWeighted<gls::DrawTestSpec::InputType>   (DE_ARRAY_BEGIN(inputTypes),            DE_ARRAY_END(inputTypes),               inputTypeWeights.weights);
2185                         attribSpec.outputType                   = random.chooseWeighted<gls::DrawTestSpec::OutputType>  (DE_ARRAY_BEGIN(outputTypes),           DE_ARRAY_END(outputTypes),              outputTypeWeights.weights);
2186                         attribSpec.storage                              = gls::DrawTestSpec::STORAGE_BUFFER;
2187                         attribSpec.usage                                = random.chooseWeighted<gls::DrawTestSpec::Usage>               (DE_ARRAY_BEGIN(usages),                        DE_ARRAY_END(usages),                   usageWeights.weights);
2188                         attribSpec.componentCount               = random.getInt(1, 4);
2189                         attribSpec.offset                               = random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(offsets), DE_ARRAY_END(offsets), offsetWeights);
2190                         attribSpec.stride                               = random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(strides), DE_ARRAY_END(strides), strideWeights);
2191                         attribSpec.normalize                    = random.getBool();
2192                         attribSpec.instanceDivisor              = random.chooseWeighted<int, const int*, const float*>(DE_ARRAY_BEGIN(instanceDivisors), DE_ARRAY_END(instanceDivisors), instanceDivisorWeights);
2193                         attribSpec.useDefaultAttribute  = random.getBool();
2194
2195                         // check spec is legal
2196                         valid = attribSpec.valid(spec.apiType);
2197
2198                         // we do not want interleaved elements. (Might result in some weird floating point values)
2199                         if (attribSpec.stride && attribSpec.componentCount * gls::DrawTestSpec::inputTypeSize(attribSpec.inputType) > attribSpec.stride)
2200                                 valid = false;
2201
2202                         // try again if not valid
2203                         if (valid)
2204                         {
2205                                 spec.attribs.push_back(attribSpec);
2206                                 ++attrNdx;
2207                         }
2208                 }
2209
2210                 // Do not collapse all vertex positions to a single positions
2211                 if (spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
2212                         spec.attribs[0].instanceDivisor = 0;
2213
2214                 // Is render result meaningful?
2215                 {
2216                         // Only one vertex
2217                         if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED && spec.indexMin == spec.indexMax && spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
2218                                 continue;
2219                         if (spec.attribs[0].useDefaultAttribute && spec.primitive != gls::DrawTestSpec::PRIMITIVE_POINTS)
2220                                 continue;
2221
2222                         // Triangle only on one axis
2223                         if (spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLES || spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLE_FAN || spec.primitive == gls::DrawTestSpec::PRIMITIVE_TRIANGLE_STRIP)
2224                         {
2225                                 if (spec.attribs[0].componentCount == 1)
2226                                         continue;
2227                                 if (spec.attribs[0].outputType == gls::DrawTestSpec::OUTPUTTYPE_FLOAT || spec.attribs[0].outputType == gls::DrawTestSpec::OUTPUTTYPE_INT || spec.attribs[0].outputType == gls::DrawTestSpec::OUTPUTTYPE_UINT)
2228                                         continue;
2229                                 if (spec.drawMethod == gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_RANGED && (spec.indexMax - spec.indexMin) < 2)
2230                                         continue;
2231                         }
2232                 }
2233
2234                 // Add case
2235                 {
2236                         deUint32 hash = spec.hash();
2237                         for (int attrNdx = 0; attrNdx < attributeCount; ++attrNdx)
2238                                 hash = (hash << 2) ^ (deUint32)spec.attribs[attrNdx].hash();
2239
2240                         if (insertedHashes.find(hash) == insertedHashes.end())
2241                         {
2242                                 // Only aligned cases
2243                                 if (spec.isCompatibilityTest() != gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_OFFSET &&
2244                                         spec.isCompatibilityTest() != gls::DrawTestSpec::COMPATIBILITY_UNALIGNED_STRIDE)
2245                                         this->addChild(new gls::DrawTest(m_testCtx, m_context.getRenderContext(), spec, de::toString(insertedCount).c_str(), spec.getDesc().c_str()));
2246                                 insertedHashes.insert(hash);
2247
2248                                 ++insertedCount;
2249                         }
2250                 }
2251         }
2252 }
2253
2254 class BadCommandBufferCase : public TestCase
2255 {
2256 public:
2257         enum
2258         {
2259                 CommandSize = 20
2260         };
2261
2262                                         BadCommandBufferCase    (Context& context, const char* name, const char* desc, deUint32 alignment, deUint32 bufferSize, bool writeCommandToBuffer, deUint32 m_expectedError);
2263                                         ~BadCommandBufferCase   (void);
2264
2265         IterateResult   iterate                                 (void);
2266
2267 private:
2268         const deUint32  m_alignment;
2269         const deUint32  m_bufferSize;
2270         const bool              m_writeCommandToBuffer;
2271         const deUint32  m_expectedError;
2272 };
2273
2274 BadCommandBufferCase::BadCommandBufferCase (Context& context, const char* name, const char* desc, deUint32 alignment, deUint32 bufferSize, bool writeCommandToBuffer, deUint32 expectedError)
2275         : TestCase                                      (context, name, desc)
2276         , m_alignment                           (alignment)
2277         , m_bufferSize                          (bufferSize)
2278         , m_writeCommandToBuffer        (writeCommandToBuffer)
2279         , m_expectedError                       (expectedError)
2280 {
2281 }
2282
2283 BadCommandBufferCase::~BadCommandBufferCase (void)
2284 {
2285 }
2286
2287 BadCommandBufferCase::IterateResult     BadCommandBufferCase::iterate (void)
2288 {
2289         const tcu::Vec4 vertexPositions[] =
2290         {
2291                 tcu::Vec4(0,    0,              0, 1),
2292                 tcu::Vec4(1,    0,              0, 1),
2293                 tcu::Vec4(0,    1,              0, 1),
2294         };
2295
2296         const deUint16 indices[] =
2297         {
2298                 0, 2, 1,
2299         };
2300
2301         DE_STATIC_ASSERT(CommandSize == sizeof(DrawElementsCommand));
2302
2303         sglr::GLContext gl(m_context.getRenderContext(), m_testCtx.getLog(), sglr::GLCONTEXT_LOG_CALLS, tcu::IVec4(0, 0, 1, 1));
2304
2305         deUint32 vaoID                  = 0;
2306         deUint32 positionBuf    = 0;
2307         deUint32 indexBuf               = 0;
2308         deUint32 drawIndirectBuf= 0;
2309         deUint32 error;
2310
2311         glu::ShaderProgram      program                 (m_context.getRenderContext(), glu::ProgramSources() << glu::VertexSource(s_commonVertexShaderSource) << glu::FragmentSource(s_commonFragmentShaderSource));
2312         deUint32                        programID               = program.getProgram();
2313         deInt32                         posLocation             = gl.getAttribLocation(programID, "a_position");
2314
2315         DrawElementsCommand drawCommand;
2316         drawCommand.count                               = 3;
2317         drawCommand.primCount                   = 1;
2318         drawCommand.firstIndex                  = 0;
2319         drawCommand.baseVertex                  = 0;
2320         drawCommand.reservedMustBeZero  = 0;
2321
2322         std::vector<deInt8> drawCommandBuffer;
2323         drawCommandBuffer.resize(m_bufferSize);
2324
2325         deMemset(&drawCommandBuffer[0], 0, (int)drawCommandBuffer.size());
2326
2327         if (m_writeCommandToBuffer)
2328         {
2329                 DE_ASSERT(drawCommandBuffer.size() >= sizeof(drawCommand) + m_alignment);
2330                 deMemcpy(&drawCommandBuffer[m_alignment], &drawCommand, sizeof(drawCommand));
2331         }
2332
2333         glu::checkError(gl.getError(), "", __FILE__, __LINE__);
2334         gl.genVertexArrays(1, &vaoID);
2335         gl.bindVertexArray(vaoID);
2336
2337         gl.genBuffers(1, &positionBuf);
2338         gl.bindBuffer(GL_ARRAY_BUFFER, positionBuf);
2339         gl.bufferData(GL_ARRAY_BUFFER, sizeof(vertexPositions), vertexPositions, GL_STATIC_DRAW);
2340         gl.vertexAttribPointer(posLocation, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
2341         gl.vertexAttribDivisor(posLocation, 0);
2342         gl.enableVertexAttribArray(posLocation);
2343         glu::checkError(gl.getError(), "", __FILE__, __LINE__);
2344
2345         gl.genBuffers(1, &indexBuf);
2346         gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuf);
2347         gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
2348         glu::checkError(gl.getError(), "", __FILE__, __LINE__);
2349
2350         gl.genBuffers(1, &drawIndirectBuf);
2351         gl.bindBuffer(GL_DRAW_INDIRECT_BUFFER, drawIndirectBuf);
2352         gl.bufferData(GL_DRAW_INDIRECT_BUFFER, drawCommandBuffer.size(), &drawCommandBuffer[0], GL_STATIC_DRAW);
2353         glu::checkError(gl.getError(), "", __FILE__, __LINE__);
2354
2355         gl.viewport(0, 0, 1, 1);
2356
2357         gl.useProgram(programID);
2358         gl.drawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, (const void*)(deUintptr)m_alignment);
2359
2360         error = gl.getError();
2361
2362         gl.useProgram(0);
2363
2364         gl.deleteBuffers(1, &drawIndirectBuf);
2365         gl.deleteBuffers(1, &indexBuf);
2366         gl.deleteBuffers(1, &positionBuf);
2367         gl.deleteVertexArrays(1, &vaoID);
2368
2369         m_testCtx.getLog() << tcu::TestLog::Message << "drawElementsIndirect generated " << glu::getErrorStr(error) << ", expecting " << glu::getErrorStr(m_expectedError) << "." << tcu::TestLog::EndMessage;
2370
2371         if (error == m_expectedError)
2372                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2373         else
2374         {
2375                 m_testCtx.getLog() << tcu::TestLog::Message << "\tUnexpected error." << tcu::TestLog::EndMessage;
2376                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got unexpected error.");
2377         }
2378
2379         return STOP;
2380 }
2381
2382 class BadAlignmentCase : public BadCommandBufferCase
2383 {
2384 public:
2385                                         BadAlignmentCase        (Context& context, const char* name, const char* desc, deUint32 alignment);
2386                                         ~BadAlignmentCase       (void);
2387 };
2388
2389 BadAlignmentCase::BadAlignmentCase (Context& context, const char* name, const char* desc, deUint32 alignment)
2390         : BadCommandBufferCase(context, name, desc, alignment, CommandSize+alignment, true, GL_INVALID_VALUE)
2391 {
2392 }
2393
2394 BadAlignmentCase::~BadAlignmentCase (void)
2395 {
2396 }
2397
2398 class BadBufferRangeCase : public BadCommandBufferCase
2399 {
2400 public:
2401                                         BadBufferRangeCase      (Context& context, const char* name, const char* desc, deUint32 offset);
2402                                         ~BadBufferRangeCase     (void);
2403 };
2404
2405 BadBufferRangeCase::BadBufferRangeCase (Context& context, const char* name, const char* desc, deUint32 offset)
2406         : BadCommandBufferCase(context, name, desc, offset, CommandSize, false, GL_INVALID_OPERATION)
2407 {
2408 }
2409
2410 BadBufferRangeCase::~BadBufferRangeCase (void)
2411 {
2412 }
2413
2414 class BadStateCase : public TestCase
2415 {
2416 public:
2417         enum CaseType
2418         {
2419                 CASE_CLIENT_BUFFER_VERTEXATTR = 0,
2420                 CASE_CLIENT_BUFFER_COMMAND,
2421                 CASE_DEFAULT_VAO,
2422
2423                 CASE_CLIENT_LAST
2424         };
2425
2426                                                 BadStateCase    (Context& context, const char* name, const char* desc, CaseType type);
2427                                                 ~BadStateCase   (void);
2428
2429         void                            init                    (void);
2430         void                            deinit                  (void);
2431         IterateResult           iterate                 (void);
2432
2433 private:
2434         const CaseType          m_caseType;
2435 };
2436
2437 BadStateCase::BadStateCase (Context& context, const char* name, const char* desc, CaseType type)
2438         : TestCase                      (context, name, desc)
2439         , m_caseType            (type)
2440 {
2441         DE_ASSERT(type < CASE_CLIENT_LAST);
2442 }
2443
2444 BadStateCase::~BadStateCase (void)
2445 {
2446         deinit();
2447 }
2448
2449 void BadStateCase::init (void)
2450 {
2451 }
2452
2453 void BadStateCase::deinit (void)
2454 {
2455 }
2456
2457 BadStateCase::IterateResult BadStateCase::iterate (void)
2458 {
2459         const tcu::Vec4 vertexPositions[] =
2460         {
2461                 tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),
2462                 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
2463                 tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
2464         };
2465
2466         const deUint16 indices[] =
2467         {
2468                 0, 2, 1,
2469         };
2470
2471         sglr::GLContext gl(m_context.getRenderContext(), m_testCtx.getLog(), sglr::GLCONTEXT_LOG_CALLS, tcu::IVec4(0, 0, 1, 1));
2472
2473         deUint32                        error;
2474         glu::ShaderProgram      program                 (m_context.getRenderContext(), glu::ProgramSources() << glu::VertexSource(s_commonVertexShaderSource) << glu::FragmentSource(s_commonFragmentShaderSource));
2475         deUint32                        vaoID                   = 0;
2476         deUint32                        dataBufferID    = 0;
2477         deUint32                        indexBufferID   = 0;
2478         deUint32                        cmdBufferID             = 0;
2479
2480         const deUint32          programID               = program.getProgram();
2481         const deInt32           posLocation             = gl.getAttribLocation(programID, "a_position");
2482
2483         DrawElementsCommand drawCommand;
2484         drawCommand.count                               = 3;
2485         drawCommand.primCount                   = 1;
2486         drawCommand.firstIndex                  = 0;
2487         drawCommand.baseVertex                  = 0;
2488         drawCommand.reservedMustBeZero  = 0;
2489
2490         glu::checkError(gl.getError(), "", __FILE__, __LINE__);
2491
2492         if (m_caseType == CASE_CLIENT_BUFFER_VERTEXATTR)
2493         {
2494                 // \note We use default VAO since we use client pointers. Trying indirect draw with default VAO is also an error. => This test does two illegal operations
2495
2496                 gl.vertexAttribPointer(posLocation, 4, GL_FLOAT, GL_FALSE, 0, vertexPositions);
2497                 gl.enableVertexAttribArray(posLocation);
2498                 glu::checkError(gl.getError(), "", __FILE__, __LINE__);
2499         }
2500         else if (m_caseType == CASE_CLIENT_BUFFER_COMMAND)
2501         {
2502                 gl.genVertexArrays(1, &vaoID);
2503                 gl.bindVertexArray(vaoID);
2504
2505                 gl.genBuffers(1, &dataBufferID);
2506                 gl.bindBuffer(GL_ARRAY_BUFFER, dataBufferID);
2507                 gl.bufferData(GL_ARRAY_BUFFER, sizeof(vertexPositions), vertexPositions, GL_STATIC_DRAW);
2508                 gl.vertexAttribPointer(posLocation, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
2509                 gl.enableVertexAttribArray(posLocation);
2510                 glu::checkError(gl.getError(), "", __FILE__, __LINE__);
2511         }
2512         else if (m_caseType == CASE_DEFAULT_VAO)
2513         {
2514                 gl.genBuffers(1, &dataBufferID);
2515                 gl.bindBuffer(GL_ARRAY_BUFFER, dataBufferID);
2516                 gl.bufferData(GL_ARRAY_BUFFER, sizeof(vertexPositions), vertexPositions, GL_STATIC_DRAW);
2517                 gl.vertexAttribPointer(posLocation, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
2518                 gl.enableVertexAttribArray(posLocation);
2519                 glu::checkError(gl.getError(), "", __FILE__, __LINE__);
2520         }
2521         else
2522                 DE_ASSERT(DE_FALSE);
2523
2524         gl.genBuffers(1, &indexBufferID);
2525         gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferID);
2526         gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
2527         glu::checkError(gl.getError(), "", __FILE__, __LINE__);
2528
2529         if (m_caseType != CASE_CLIENT_BUFFER_COMMAND)
2530         {
2531                 gl.genBuffers(1, &cmdBufferID);
2532                 gl.bindBuffer(GL_DRAW_INDIRECT_BUFFER, cmdBufferID);
2533                 gl.bufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(drawCommand), &drawCommand, GL_STATIC_DRAW);
2534                 glu::checkError(gl.getError(), "", __FILE__, __LINE__);
2535         }
2536
2537         gl.viewport(0, 0, 1, 1);
2538
2539         gl.useProgram(programID);
2540         gl.drawElementsIndirect(GL_TRIANGLES, GL_UNSIGNED_SHORT, (m_caseType != CASE_CLIENT_BUFFER_COMMAND) ? (DE_NULL) : (&drawCommand));
2541
2542         error = gl.getError();
2543
2544         gl.bindVertexArray(0);
2545         gl.useProgram(0);
2546
2547         if (error == GL_INVALID_OPERATION)
2548                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2549         else
2550         {
2551                 m_testCtx.getLog() << tcu::TestLog::Message << "Unexpected error. Expected GL_INVALID_OPERATION, got " << glu::getErrorStr(error) << tcu::TestLog::EndMessage;
2552                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got unexpected error.");
2553         }
2554
2555         return STOP;
2556 }
2557
2558 class BadDrawModeCase : public TestCase
2559 {
2560 public:
2561         enum DrawType
2562         {
2563                 DRAW_ARRAYS = 0,
2564                 DRAW_ELEMENTS,
2565                 DRAW_ELEMENTS_BAD_INDEX,
2566
2567                 DRAW_LAST
2568         };
2569
2570                                                 BadDrawModeCase (Context& context, const char* name, const char* desc, DrawType type);
2571                                                 ~BadDrawModeCase(void);
2572
2573         void                            init                    (void);
2574         void                            deinit                  (void);
2575         IterateResult           iterate                 (void);
2576
2577 private:
2578         const DrawType          m_drawType;
2579 };
2580
2581 BadDrawModeCase::BadDrawModeCase (Context& context, const char* name, const char* desc, DrawType type)
2582         : TestCase                      (context, name, desc)
2583         , m_drawType            (type)
2584 {
2585         DE_ASSERT(type < DRAW_LAST);
2586 }
2587
2588 BadDrawModeCase::~BadDrawModeCase (void)
2589 {
2590         deinit();
2591 }
2592
2593 void BadDrawModeCase::init (void)
2594 {
2595 }
2596
2597 void BadDrawModeCase::deinit (void)
2598 {
2599 }
2600
2601 BadDrawModeCase::IterateResult BadDrawModeCase::iterate (void)
2602 {
2603         const tcu::Vec4 vertexPositions[] =
2604         {
2605                 tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),
2606                 tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f),
2607                 tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
2608         };
2609
2610         const deUint16 indices[] =
2611         {
2612                 0, 2, 1,
2613         };
2614
2615         sglr::GLContext         gl                              (m_context.getRenderContext(), m_testCtx.getLog(), sglr::GLCONTEXT_LOG_CALLS, tcu::IVec4(0, 0, 1, 1));
2616
2617         deUint32                        error;
2618         glu::ShaderProgram      program                 (m_context.getRenderContext(), glu::ProgramSources() << glu::VertexSource(s_commonVertexShaderSource) << glu::FragmentSource(s_commonFragmentShaderSource));
2619         deUint32                        vaoID                   = 0;
2620         deUint32                        dataBufferID    = 0;
2621         deUint32                        indexBufferID   = 0;
2622         deUint32                        cmdBufferID             = 0;
2623
2624         const deUint32          programID               = program.getProgram();
2625         const deInt32           posLocation             = gl.getAttribLocation(programID, "a_position");
2626         const glw::GLenum       mode                    = (m_drawType == DRAW_ELEMENTS_BAD_INDEX) ? (GL_TRIANGLES) : (0x123);
2627         const glw::GLenum       indexType               = (m_drawType == DRAW_ELEMENTS_BAD_INDEX) ? (0x123) : (GL_UNSIGNED_SHORT);
2628
2629         glu::checkError(gl.getError(), "", __FILE__, __LINE__);
2630
2631         // vao
2632
2633         gl.genVertexArrays(1, &vaoID);
2634         gl.bindVertexArray(vaoID);
2635
2636         // va
2637
2638         gl.genBuffers(1, &dataBufferID);
2639         gl.bindBuffer(GL_ARRAY_BUFFER, dataBufferID);
2640         gl.bufferData(GL_ARRAY_BUFFER, sizeof(vertexPositions), vertexPositions, GL_STATIC_DRAW);
2641         gl.vertexAttribPointer(posLocation, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
2642         gl.enableVertexAttribArray(posLocation);
2643         glu::checkError(gl.getError(), "", __FILE__, __LINE__);
2644
2645         // index
2646
2647         if (m_drawType == DRAW_ELEMENTS || m_drawType == DRAW_ELEMENTS_BAD_INDEX)
2648         {
2649                 gl.genBuffers(1, &indexBufferID);
2650                 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferID);
2651                 gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
2652                 glu::checkError(gl.getError(), "", __FILE__, __LINE__);
2653         }
2654
2655         // cmd
2656
2657         gl.genBuffers(1, &cmdBufferID);
2658         gl.bindBuffer(GL_DRAW_INDIRECT_BUFFER, cmdBufferID);
2659         if (m_drawType == DRAW_ELEMENTS || m_drawType == DRAW_ELEMENTS_BAD_INDEX)
2660         {
2661                 DrawElementsCommand drawCommand;
2662                 drawCommand.count                               = 3;
2663                 drawCommand.primCount                   = 1;
2664                 drawCommand.firstIndex                  = 0;
2665                 drawCommand.baseVertex                  = 0;
2666                 drawCommand.reservedMustBeZero  = 0;
2667
2668                 gl.bufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(drawCommand), &drawCommand, GL_STATIC_DRAW);
2669         }
2670         else if (m_drawType == DRAW_ARRAYS)
2671         {
2672                 DrawArraysCommand drawCommand;
2673                 drawCommand.count                               = 3;
2674                 drawCommand.primCount                   = 1;
2675                 drawCommand.first                               = 0;
2676                 drawCommand.reservedMustBeZero  = 0;
2677
2678                 gl.bufferData(GL_DRAW_INDIRECT_BUFFER, sizeof(drawCommand), &drawCommand, GL_STATIC_DRAW);
2679         }
2680         else
2681                 DE_ASSERT(DE_FALSE);
2682         glu::checkError(gl.getError(), "", __FILE__, __LINE__);
2683
2684         gl.viewport(0, 0, 1, 1);
2685         gl.useProgram(programID);
2686         if (m_drawType == DRAW_ELEMENTS || m_drawType == DRAW_ELEMENTS_BAD_INDEX)
2687                 gl.drawElementsIndirect(mode, indexType, DE_NULL);
2688         else if (m_drawType == DRAW_ARRAYS)
2689                 gl.drawArraysIndirect(mode, DE_NULL);
2690         else
2691                 DE_ASSERT(DE_FALSE);
2692
2693         error = gl.getError();
2694         gl.useProgram(0);
2695
2696         if (error == GL_INVALID_ENUM)
2697                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2698         else
2699         {
2700                 m_testCtx.getLog() << tcu::TestLog::Message << "Unexpected error. Expected GL_INVALID_ENUM, got " << glu::getErrorStr(error) << tcu::TestLog::EndMessage;
2701                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Got unexpected error.");
2702         }
2703
2704         return STOP;
2705 }
2706
2707 class NegativeGroup : public TestCaseGroup
2708 {
2709 public:
2710                         NegativeGroup   (Context& context, const char* name, const char* descr);
2711                         ~NegativeGroup  (void);
2712
2713         void    init                    (void);
2714 };
2715
2716 NegativeGroup::NegativeGroup (Context& context, const char* name, const char* descr)
2717         : TestCaseGroup (context, name, descr)
2718 {
2719 }
2720
2721 NegativeGroup::~NegativeGroup (void)
2722 {
2723 }
2724
2725 void NegativeGroup::init (void)
2726 {
2727         // invalid alignment
2728         addChild(new BadAlignmentCase   (m_context, "command_bad_alignment_1",                                                          "Bad command alignment",                                        1));
2729         addChild(new BadAlignmentCase   (m_context, "command_bad_alignment_2",                                                          "Bad command alignment",                                        2));
2730         addChild(new BadAlignmentCase   (m_context, "command_bad_alignment_3",                                                          "Bad command alignment",                                        3));
2731
2732         // command only partially or not at all in the buffer
2733         addChild(new BadBufferRangeCase (m_context, "command_offset_partially_in_buffer",                                       "Command not fully in the buffer range",        BadBufferRangeCase::CommandSize - 16));
2734         addChild(new BadBufferRangeCase (m_context, "command_offset_not_in_buffer",                                                     "Command not in the buffer range",                      BadBufferRangeCase::CommandSize));
2735         addChild(new BadBufferRangeCase (m_context, "command_offset_not_in_buffer_unsigned32_wrap",                     "Command not in the buffer range",                      0xFFFFFFFC));
2736         addChild(new BadBufferRangeCase (m_context, "command_offset_not_in_buffer_signed32_wrap",                       "Command not in the buffer range",                      0x7FFFFFFC));
2737
2738         // use with client data and default vao
2739         addChild(new BadStateCase               (m_context, "client_vertex_attrib_array",                                                       "Vertex attrib array in the client memory",     BadStateCase::CASE_CLIENT_BUFFER_VERTEXATTR));
2740         addChild(new BadStateCase               (m_context, "client_command_array",                                                                     "Command array in the client memory",           BadStateCase::CASE_CLIENT_BUFFER_COMMAND));
2741         addChild(new BadStateCase               (m_context, "default_vao",                                                                                      "Use with default vao",                                         BadStateCase::CASE_DEFAULT_VAO));
2742
2743         // invalid mode & type
2744         addChild(new BadDrawModeCase    (m_context, "invalid_mode_draw_arrays",                                                         "Call DrawArraysIndirect with bad mode",        BadDrawModeCase::DRAW_ARRAYS));
2745         addChild(new BadDrawModeCase    (m_context, "invalid_mode_draw_elements",                                                       "Call DrawelementsIndirect with bad mode",      BadDrawModeCase::DRAW_ELEMENTS));
2746         addChild(new BadDrawModeCase    (m_context, "invalid_type_draw_elements",                                                       "Call DrawelementsIndirect with bad type",      BadDrawModeCase::DRAW_ELEMENTS_BAD_INDEX));
2747 }
2748
2749 } // anonymous
2750
2751 DrawTests::DrawTests (Context& context)
2752         : TestCaseGroup(context, "draw_indirect", "Indirect drawing tests")
2753 {
2754 }
2755
2756 DrawTests::~DrawTests (void)
2757 {
2758 }
2759
2760 void DrawTests::init (void)
2761 {
2762         // Basic
2763         {
2764                 const gls::DrawTestSpec::DrawMethod basicMethods[] =
2765                 {
2766                         gls::DrawTestSpec::DRAWMETHOD_DRAWARRAYS_INDIRECT,
2767                         gls::DrawTestSpec::DRAWMETHOD_DRAWELEMENTS_INDIRECT,
2768                 };
2769
2770                 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(basicMethods); ++ndx)
2771                 {
2772                         const std::string name = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]);
2773                         const std::string desc = gls::DrawTestSpec::drawMethodToString(basicMethods[ndx]);
2774
2775                         this->addChild(new MethodGroup(m_context, name.c_str(), desc.c_str(), basicMethods[ndx]));
2776                 }
2777         }
2778
2779         // extreme instancing
2780
2781         this->addChild(new InstancingGroup(m_context, "instancing", "draw tests with a large instance count."));
2782
2783         // compute shader generated commands
2784
2785         this->addChild(new ComputeShaderGeneratedGroup(m_context, "compute_interop", "draw tests with a draw command generated in compute shader."));
2786
2787         // Random
2788
2789         this->addChild(new RandomGroup(m_context, "random", "random draw commands."));
2790
2791         // negative
2792
2793         this->addChild(new NegativeGroup(m_context, "negative", "invalid draw commands with defined error codes."));
2794 }
2795
2796 } // Functional
2797 } // gles31
2798 } // deqp