Map buffers for writing in atomic counter tests
[platform/upstream/VK-GL-CTS.git] / external / openglcts / modules / gles31 / es31cShaderAtomicCountersTests.cpp
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2014-2016 The Khronos Group Inc.
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
22  */ /*-------------------------------------------------------------------*/
23
24 #include "es31cShaderAtomicCountersTests.hpp"
25 #include "gluContextInfo.hpp"
26 #include "gluPixelTransfer.hpp"
27 #include "glwEnums.hpp"
28 #include "glwFunctions.hpp"
29 #include "tcuImageCompare.hpp"
30 #include "tcuRenderTarget.hpp"
31 #include "tcuSurface.hpp"
32 #include "tcuVector.hpp"
33 #include <assert.h>
34 #include <cstdarg>
35 #include <map>
36
37 namespace glcts
38 {
39 using namespace glw;
40 using tcu::Vec4;
41 using tcu::UVec4;
42
43 namespace
44 {
45
46 static tcu::TestLog* currentLog;
47
48 void setOutput(tcu::TestLog& log)
49 {
50         currentLog = &log;
51 }
52
53 void Output(const char* format, ...)
54 {
55         va_list args;
56         va_start(args, format);
57
58         const int   MAX_OUTPUT_STRING_SIZE = 40000;
59         static char temp[MAX_OUTPUT_STRING_SIZE];
60
61         vsnprintf(temp, MAX_OUTPUT_STRING_SIZE - 1, format, args);
62         temp[MAX_OUTPUT_STRING_SIZE - 1] = '\0';
63
64         char* logLine = strtok(temp, "\n");
65         while (logLine != NULL)
66         {
67                 currentLog->writeMessage(logLine);
68                 logLine = strtok(NULL, "\n");
69         }
70         va_end(args);
71 }
72
73 class SACSubcaseBase : public glcts::SubcaseBase
74 {
75 public:
76         virtual std::string Title()
77         {
78                 return NL "";
79         }
80         virtual std::string Purpose()
81         {
82                 return NL "";
83         }
84         virtual std::string Method()
85         {
86                 return NL "";
87         }
88         virtual std::string PassCriteria()
89         {
90                 return NL "";
91         }
92
93         virtual ~SACSubcaseBase()
94         {
95         }
96
97         bool CheckProgram(GLuint program)
98         {
99                 GLint status;
100                 glGetProgramiv(program, GL_LINK_STATUS, &status);
101                 GLint length;
102                 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
103                 if (length > 1)
104                 {
105                         std::vector<GLchar> log(length);
106                         glGetProgramInfoLog(program, length, NULL, &log[0]);
107                         Output("%s\n", &log[0]);
108                 }
109                 return status == GL_TRUE;
110         }
111
112         int getWindowWidth()
113         {
114                 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
115                 return renderTarget.getWidth();
116         }
117
118         int getWindowHeight()
119         {
120                 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
121                 return renderTarget.getHeight();
122         }
123
124         long ValidateReadBuffer(const Vec4& expected)
125         {
126                 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
127                 int                                              viewportW      = renderTarget.getWidth();
128                 int                                              viewportH      = renderTarget.getHeight();
129                 tcu::Surface                     renderedFrame(viewportW, viewportH);
130                 tcu::Surface                     referenceFrame(viewportW, viewportH);
131
132                 glu::readPixels(m_context.getRenderContext(), 0, 0, renderedFrame.getAccess());
133
134                 for (int y = 0; y < viewportH; ++y)
135                 {
136                         for (int x = 0; x < viewportW; ++x)
137                         {
138                                 referenceFrame.setPixel(
139                                         x, y, tcu::RGBA(static_cast<int>(expected[0] * 255), static_cast<int>(expected[1] * 255),
140                                                                         static_cast<int>(expected[2] * 255), static_cast<int>(expected[3] * 255)));
141                         }
142                 }
143                 tcu::TestLog& log = m_context.getTestContext().getLog();
144                 bool isOk = tcu::fuzzyCompare(log, "Result", "Image comparison result", referenceFrame, renderedFrame, 0.05f,
145                                                                           tcu::COMPARE_LOG_RESULT);
146                 return (isOk ? NO_ERROR : ERROR);
147         }
148
149         void LinkProgram(GLuint program)
150         {
151                 glLinkProgram(program);
152                 GLsizei length;
153                 GLchar  log[1024];
154                 glGetProgramInfoLog(program, sizeof(log), &length, log);
155                 if (length > 1)
156                 {
157                         Output("Program Info Log:\n%s\n", log);
158                 }
159         }
160
161         GLuint CreateProgram(const char* src_vs, const char* src_fs, bool link)
162         {
163                 const GLuint p = glCreateProgram();
164
165                 if (src_vs)
166                 {
167                         GLuint sh = glCreateShader(GL_VERTEX_SHADER);
168                         glAttachShader(p, sh);
169                         glDeleteShader(sh);
170                         glShaderSource(sh, 1, &src_vs, NULL);
171                         glCompileShader(sh);
172                 }
173                 if (src_fs)
174                 {
175                         GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
176                         glAttachShader(p, sh);
177                         glDeleteShader(sh);
178                         glShaderSource(sh, 1, &src_fs, NULL);
179                         glCompileShader(sh);
180                 }
181                 if (link)
182                 {
183                         LinkProgram(p);
184                 }
185                 return p;
186         }
187
188         GLuint CreateShaderProgram(GLenum type, GLsizei count, const GLchar** strings)
189         {
190                 GLuint program = glCreateShaderProgramv(type, count, strings);
191                 GLint  status  = GL_TRUE;
192                 glGetProgramiv(program, GL_LINK_STATUS, &status);
193                 if (status == GL_FALSE)
194                 {
195                         GLsizei length;
196                         GLchar  log[1024];
197                         glGetProgramInfoLog(program, sizeof(log), &length, log);
198                         if (length > 1)
199                         {
200                                 Output("Program Info Log:\n%s\n", log);
201                         }
202                 }
203                 return program;
204         }
205
206         void CreateQuad(GLuint* vao, GLuint* vbo, GLuint* ebo)
207         {
208                 assert(vao && vbo);
209
210                 // interleaved data (vertex, color0 (green), color1 (blue), color2 (red))
211                 const float v[] = {
212                         -1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,  1.0f, 0.0f, 0.0f, 1.0f, -1.0f, 0.0f, 1.0f,
213                         0.0f,  0.0f,  0.0f, 1.0f, 1.0f, 0.0f, 0.0f, -1.0f, 1.0f, 0.0f, 1.0f, 0.0f, 0.0f,  0.0f, 1.0f,
214                         1.0f,  0.0f,  0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f,  0.0f, 0.0f, 1.0f, 1.0f, 0.0f,  0.0f,
215                 };
216                 glGenBuffers(1, vbo);
217                 glBindBuffer(GL_ARRAY_BUFFER, *vbo);
218                 glBufferData(GL_ARRAY_BUFFER, sizeof(v), v, GL_STATIC_DRAW);
219                 glBindBuffer(GL_ARRAY_BUFFER, 0);
220
221                 if (ebo)
222                 {
223                         std::vector<GLushort> index_data(4);
224                         for (int i = 0; i < 4; ++i)
225                         {
226                                 index_data[i] = static_cast<GLushort>(i);
227                         }
228                         glGenBuffers(1, ebo);
229                         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *ebo);
230                         glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * 4, &index_data[0], GL_STATIC_DRAW);
231                         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
232                 }
233
234                 glGenVertexArrays(1, vao);
235                 glBindVertexArray(*vao);
236                 glBindBuffer(GL_ARRAY_BUFFER, *vbo);
237                 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 11, 0);
238                 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 2));
239                 glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 5));
240                 glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 8));
241                 glBindBuffer(GL_ARRAY_BUFFER, 0);
242                 glEnableVertexAttribArray(0);
243                 glEnableVertexAttribArray(1);
244                 glEnableVertexAttribArray(2);
245                 glEnableVertexAttribArray(3);
246                 if (ebo)
247                 {
248                         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *ebo);
249                 }
250                 glBindVertexArray(0);
251         }
252
253         void CreateTriangle(GLuint* vao, GLuint* vbo, GLuint* ebo)
254         {
255                 assert(vao && vbo);
256
257                 // interleaved data (vertex, color0 (green), color1 (blue), color2 (red))
258                 const float v[] = {
259                         -1.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f,  0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 3.0f, -1.0f, 0.0f, 1.0f, 0.0f, 0.0f,
260                         0.0f,  1.0f,  1.0f, 0.0f, 0.0f, -1.0f, 3.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f,  1.0f, 0.0f, 0.0f,
261                 };
262                 glGenBuffers(1, vbo);
263                 glBindBuffer(GL_ARRAY_BUFFER, *vbo);
264                 glBufferData(GL_ARRAY_BUFFER, sizeof(v), v, GL_STATIC_DRAW);
265                 glBindBuffer(GL_ARRAY_BUFFER, 0);
266
267                 if (ebo)
268                 {
269                         std::vector<GLushort> index_data(3);
270                         for (int i = 0; i < 3; ++i)
271                         {
272                                 index_data[i] = static_cast<GLushort>(i);
273                         }
274                         glGenBuffers(1, ebo);
275                         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *ebo);
276                         glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLushort) * 4, &index_data[0], GL_STATIC_DRAW);
277                         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
278                 }
279
280                 glGenVertexArrays(1, vao);
281                 glBindVertexArray(*vao);
282                 glBindBuffer(GL_ARRAY_BUFFER, *vbo);
283                 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(float) * 11, 0);
284                 glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 2));
285                 glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 5));
286                 glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 11, reinterpret_cast<void*>(sizeof(float) * 8));
287                 glBindBuffer(GL_ARRAY_BUFFER, 0);
288                 glEnableVertexAttribArray(0);
289                 glEnableVertexAttribArray(1);
290                 glEnableVertexAttribArray(2);
291                 glEnableVertexAttribArray(3);
292                 if (ebo)
293                 {
294                         glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *ebo);
295                 }
296                 glBindVertexArray(0);
297         }
298
299         const char* GLenumToString(GLenum e)
300         {
301                 switch (e)
302                 {
303                 case GL_ATOMIC_COUNTER_BUFFER_BINDING:
304                         return "GL_ATOMIC_COUNTER_BUFFER_BINDING";
305                 case GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS:
306                         return "GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS";
307                 case GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS:
308                         return "GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS";
309                 case GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS:
310                         return "GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS";
311                 case GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS:
312                         return "GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS";
313
314                 case GL_MAX_VERTEX_ATOMIC_COUNTERS:
315                         return "GL_MAX_VERTEX_ATOMIC_COUNTERS";
316                 case GL_MAX_COMPUTE_ATOMIC_COUNTERS:
317                         return "GL_MAX_GEOMETRY_ATOMIC_COUNTERS";
318                 case GL_MAX_FRAGMENT_ATOMIC_COUNTERS:
319                         return "GL_MAX_FRAGMENT_ATOMIC_COUNTERS";
320                 case GL_MAX_COMBINED_ATOMIC_COUNTERS:
321                         return "GL_MAX_COMBINED_ATOMIC_COUNTERS";
322
323                 case GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE:
324                         return "GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE";
325                 case GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS:
326                         return "GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS";
327
328                 default:
329                         assert(0);
330                         break;
331                 }
332                 return NULL;
333         }
334
335         bool CheckMaxValue(GLenum e, GLint expected)
336         {
337                 bool ok = true;
338
339                 GLint i;
340                 glGetIntegerv(e, &i);
341                 Output("%s = %d\n", GLenumToString(e), i);
342                 if (i < expected)
343                 {
344                         ok = false;
345                         Output("%s state is incorrect (GetIntegerv, is: %d, expected: %d)\n", GLenumToString(e), i, expected);
346                 }
347
348                 GLint64 i64;
349                 glGetInteger64v(e, &i64);
350                 if (i64 < static_cast<GLint64>(expected))
351                 {
352                         ok = false;
353                         Output("%s state is incorrect (GetInteger64v, is: %d, expected: %d)\n", GLenumToString(e),
354                                    static_cast<GLint>(i64), expected);
355                 }
356
357                 GLfloat f;
358                 glGetFloatv(e, &f);
359                 if (f < static_cast<GLfloat>(expected))
360                 {
361                         ok = false;
362                         Output("%s state is incorrect (GetFloatv, is: %f, expected: %d)\n", GLenumToString(e), f, expected);
363                 }
364
365                 GLboolean b;
366                 glGetBooleanv(e, &b);
367
368                 return ok;
369         }
370
371         bool CheckGetCommands(GLenum e, GLint expected)
372         {
373                 bool ok = true;
374
375                 GLint i;
376                 glGetIntegerv(e, &i);
377                 if (i != expected)
378                 {
379                         ok = false;
380                         Output("%s state is incorrect (GetIntegerv, is: %d, expected: %d)\n", GLenumToString(e), i, expected);
381                 }
382
383                 GLint64 i64;
384                 glGetInteger64v(e, &i64);
385                 if (i64 != static_cast<GLint64>(expected))
386                 {
387                         ok = false;
388                         Output("%s state is incorrect (GetInteger64v, is: %d, expected: %d)\n", GLenumToString(e),
389                                    static_cast<GLint>(i64), expected);
390                 }
391
392                 GLfloat f;
393                 glGetFloatv(e, &f);
394                 if (f != static_cast<GLfloat>(expected))
395                 {
396                         ok = false;
397                         Output("%s state is incorrect (GetFloatv, is: %f, expected: %d)\n", GLenumToString(e), f, expected);
398                 }
399
400                 GLboolean b;
401                 glGetBooleanv(e, &b);
402                 if (b != (expected ? GL_TRUE : GL_FALSE))
403                 {
404                         ok = false;
405                         Output("%s state is incorrect (GetBooleanv, is: %d, expected: %d)\n", GLenumToString(e), b,
406                                    expected ? GL_TRUE : GL_FALSE);
407                 }
408
409                 return ok;
410         }
411
412         bool CheckBufferBindingState(GLuint index, GLint binding, GLint64 start, GLint64 size)
413         {
414                 bool ok = true;
415
416                 GLint i;
417                 glGetIntegeri_v(GL_ATOMIC_COUNTER_BUFFER_BINDING, index, &i);
418                 if (i != binding)
419                 {
420                         ok = false;
421                         Output("GL_ATOMIC_COUNTER_BUFFER_BINDING state is incorrect (GetIntegeri_v, is: %d, expected: %d, index: "
422                                    "%u)\n",
423                                    i, binding, index);
424                 }
425
426                 GLint64 i64;
427                 glGetInteger64i_v(GL_ATOMIC_COUNTER_BUFFER_BINDING, index, &i64);
428                 if (i64 != static_cast<GLint64>(binding))
429                 {
430                         ok = false;
431                         Output("GL_ATOMIC_COUNTER_BUFFER_BINDING state is incorrect (GetInteger64i_v, is: %d, expected: %d, index: "
432                                    "%u)\n",
433                                    static_cast<GLint>(i64), binding, index);
434                 }
435
436                 glGetInteger64i_v(GL_ATOMIC_COUNTER_BUFFER_START, index, &i64);
437                 if (i64 != start)
438                 {
439                         ok = false;
440                         Output("GL_ATOMIC_COUNTER_BUFFER_START state is incorrect (GetInteger64i_v, is: %d, expected: %d, index: "
441                                    "%u)\n",
442                                    static_cast<GLint>(i64), static_cast<GLint>(start), index);
443                 }
444                 glGetInteger64i_v(GL_ATOMIC_COUNTER_BUFFER_SIZE, index, &i64);
445                 if (i64 != size && i64 != 0)
446                 {
447                         ok = false;
448                         Output("GL_ATOMIC_COUNTER_BUFFER_SIZE state is incorrect (GetInteger64i_v, is: %d, expected: (%d or 0), "
449                                    "index: %u)\n",
450                                    static_cast<GLint>(i64), static_cast<GLint>(size), index);
451                 }
452
453                 return ok;
454         }
455
456         bool CheckUniform(GLuint prog, const GLchar* uniform_name, GLuint uniform_index, GLint uniform_type,
457                                           GLint uniform_size, GLint uniform_offset, GLint uniform_array_stride)
458         {
459                 bool ok = true;
460
461                 GLuint index;
462                 glGetUniformIndices(prog, 1, &uniform_name, &index);
463                 if (index != uniform_index)
464                 {
465                         Output("Uniform: %s: Bad index returned by glGetUniformIndices.\n", uniform_name);
466                         ok = false;
467                 }
468
469                 const GLsizei uniform_length = static_cast<GLsizei>(strlen(uniform_name));
470
471                 GLsizei length;
472                 GLint   size;
473                 GLenum  type;
474                 GLchar  name[32];
475
476                 glGetProgramResourceName(prog, GL_UNIFORM, uniform_index, sizeof(name), &length, name);
477                 if (length != uniform_length)
478                 {
479                         Output("Uniform: %s: Length is %d should be %d.\n", uniform_name, length, uniform_length);
480                         ok = false;
481                 }
482                 glGetActiveUniform(prog, uniform_index, sizeof(name), &length, &size, &type, name);
483                 if (strcmp(name, uniform_name))
484                 {
485                         Output("Uniform: %s: Bad name returned by glGetActiveUniform.\n", uniform_name);
486                         ok = false;
487                 }
488                 if (length != uniform_length)
489                 {
490                         Output("Uniform: %s: Length is %d should be %d.\n", uniform_name, length, uniform_length);
491                         ok = false;
492                 }
493                 if (size != uniform_size)
494                 {
495                         Output("Uniform: %s: Size is %d should be %d.\n", uniform_name, size, uniform_size);
496                         ok = false;
497                 }
498                 if (type != static_cast<GLenum>(uniform_type))
499                 {
500                         Output("Uniform: %s: Type is %d should be %d.\n", uniform_name, type, uniform_type);
501                         ok = false;
502                 }
503
504                 GLint param;
505                 glGetActiveUniformsiv(prog, 1, &uniform_index, GL_UNIFORM_TYPE, &param);
506                 if (param != uniform_type)
507                 {
508                         Output("Uniform: %s: Type is %d should be %d.\n", uniform_name, param, uniform_type);
509                         ok = false;
510                 }
511                 glGetActiveUniformsiv(prog, 1, &uniform_index, GL_UNIFORM_SIZE, &param);
512                 if (param != uniform_size)
513                 {
514                         Output("Uniform: %s: GL_UNIFORM_SIZE is %d should be %d.\n", uniform_name, param, uniform_size);
515                         ok = false;
516                 }
517                 glGetActiveUniformsiv(prog, 1, &uniform_index, GL_UNIFORM_NAME_LENGTH, &param);
518                 if (param != (uniform_length + 1))
519                 {
520                         Output("Uniform: %s: GL_UNIFORM_NAME_LENGTH is %d should be %d.\n", uniform_name, param,
521                                    uniform_length + 1);
522                         ok = false;
523                 }
524                 glGetActiveUniformsiv(prog, 1, &uniform_index, GL_UNIFORM_BLOCK_INDEX, &param);
525                 if (param != -1)
526                 {
527                         Output("Uniform: %s: GL_UNIFORM_BLOCK_INDEX should be -1.\n", uniform_name);
528                         ok = false;
529                 }
530                 glGetActiveUniformsiv(prog, 1, &uniform_index, GL_UNIFORM_OFFSET, &param);
531                 if (param != uniform_offset)
532                 {
533                         Output("Uniform: %s: GL_UNIFORM_OFFSET is %d should be %d.\n", uniform_name, param, uniform_offset);
534                         ok = false;
535                 }
536                 glGetActiveUniformsiv(prog, 1, &uniform_index, GL_UNIFORM_ARRAY_STRIDE, &param);
537                 if (param != uniform_array_stride)
538                 {
539                         Output("Uniform: %s: GL_UNIFORM_ARRAY_STRIDE is %d should be %d.\n", uniform_name, param,
540                                    uniform_array_stride);
541                         ok = false;
542                 }
543                 glGetActiveUniformsiv(prog, 1, &uniform_index, GL_UNIFORM_MATRIX_STRIDE, &param);
544                 if (param != 0)
545                 {
546                         Output("Uniform: %s: GL_UNIFORM_MATRIX_STRIDE should be 0 is %d.\n", uniform_name, param);
547                         ok = false;
548                 }
549                 glGetActiveUniformsiv(prog, 1, &uniform_index, GL_UNIFORM_IS_ROW_MAJOR, &param);
550                 if (param != 0)
551                 {
552                         Output("Uniform: %s: GL_UNIFORM_IS_ROW_MAJOR should be 0 is %d.\n", uniform_name, param);
553                         ok = false;
554                 }
555
556                 return ok;
557         }
558
559         bool CheckCounterValues(GLuint size, GLuint* values, GLuint min_value)
560         {
561                 std::sort(values, values + size);
562                 for (GLuint i = 0; i < size; ++i)
563                 {
564                         Output("%u\n", values[i]);
565                         if (values[i] != i + min_value)
566                         {
567                                 Output("Counter value is %u should be %u.\n", values[i], i + min_value);
568                                 return false;
569                         }
570                 }
571                 return true;
572         }
573
574         bool CheckCounterValues(GLuint size, UVec4* data, GLuint min_value)
575         {
576                 std::vector<GLuint> values(size);
577                 for (GLuint j = 0; j < size; ++j)
578                 {
579                         values[j] = data[j].x();
580                 }
581                 std::sort(values.begin(), values.end());
582                 for (GLuint i = 0; i < size; ++i)
583                 {
584                         Output("%u\n", values[i]);
585                         if (values[i] != i + min_value)
586                         {
587                                 Output("Counter value is %u should be %u.\n", values[i], i + min_value);
588                                 return false;
589                         }
590                 }
591                 return true;
592         }
593
594         bool CheckFinalCounterValue(GLuint buffer, GLintptr offset, GLuint expected_value)
595         {
596                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, buffer);
597                 GLuint* value = static_cast<GLuint*>(glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, offset, 4, GL_MAP_READ_BIT));
598                 if (value[0] != expected_value)
599                 {
600                         Output("Counter value is %u should be %u.\n", value, expected_value);
601                         glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
602                         glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
603                         return false;
604                 }
605                 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
606                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
607                 return true;
608         }
609 };
610
611 class Buffer : public glcts::GLWrapper
612 {
613 public:
614         Buffer()
615                 : size_(0)
616                 , usage_(GL_STATIC_DRAW)
617                 , access_(GL_WRITE_ONLY)
618                 , access_flags_(0)
619                 , mapped_(GL_FALSE)
620                 , map_pointer_(NULL)
621                 , map_offset_(0)
622                 , map_length_(0)
623         {
624                 glGenBuffers(1, &name_);
625                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, name_);
626                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
627         }
628         ~Buffer()
629         {
630                 glDeleteBuffers(1, &name_);
631         }
632         GLuint name() const
633         {
634                 return name_;
635         }
636         long Verify()
637         {
638                 GLint   i;
639                 GLint64 i64;
640
641                 glGetBufferParameteri64v(GL_ATOMIC_COUNTER_BUFFER, GL_BUFFER_SIZE, &i64);
642                 if (i64 != size_)
643                 {
644                         Output("BUFFER_SIZE is %d should be %d.\n", static_cast<GLint>(i64), static_cast<GLint>(size_));
645                         return ERROR;
646                 }
647                 glGetBufferParameteriv(GL_ATOMIC_COUNTER_BUFFER, GL_BUFFER_USAGE, &i);
648                 if (i != static_cast<GLint>(usage_))
649                 {
650                         Output("BUFFER_USAGE is %d should be %d.\n", i, usage_);
651                         return ERROR;
652                 }
653                 if (this->m_context.getContextInfo().isExtensionSupported("GL_OES_mapbuffer"))
654                 {
655                         glGetBufferParameteriv(GL_ATOMIC_COUNTER_BUFFER, GL_BUFFER_ACCESS, &i);
656                         if (i != static_cast<GLint>(access_))
657                         {
658                                 Output("BUFFER_ACCESS is %d should be %d.\n", i, access_);
659                                 return ERROR;
660                         }
661                 }
662                 else
663                 {
664                         Output("GL_OES_mapbuffer not supported, skipping GL_BUFFER_ACCESS enum");
665                 }
666                 glGetBufferParameteriv(GL_ATOMIC_COUNTER_BUFFER, GL_BUFFER_ACCESS_FLAGS, &i);
667                 if (i != access_flags_)
668                 {
669                         Output("BUFFER_ACCESS_FLAGS is %d should be %d.\n", i, access_flags_);
670                         return ERROR;
671                 }
672                 glGetBufferParameteriv(GL_ATOMIC_COUNTER_BUFFER, GL_BUFFER_MAPPED, &i);
673                 if (i != mapped_)
674                 {
675                         Output("BUFFER_MAPPED is %d should be %d.\n", i, mapped_);
676                         return ERROR;
677                 }
678                 glGetBufferParameteri64v(GL_ATOMIC_COUNTER_BUFFER, GL_BUFFER_MAP_OFFSET, &i64);
679                 if (i64 != map_offset_)
680                 {
681                         Output("BUFFER_MAP_OFFSET is %d should be %d.\n", static_cast<GLint>(i64), static_cast<GLint>(map_offset_));
682                         return ERROR;
683                 }
684                 glGetBufferParameteri64v(GL_ATOMIC_COUNTER_BUFFER, GL_BUFFER_MAP_LENGTH, &i64);
685                 if (i64 != map_length_)
686                 {
687                         Output("BUFFER_MAP_LENGTH is %d should be %d.\n", static_cast<GLint>(i64), static_cast<GLint>(map_length_));
688                         return ERROR;
689                 }
690                 void* ptr;
691                 glGetBufferPointerv(GL_ATOMIC_COUNTER_BUFFER, GL_BUFFER_MAP_POINTER, &ptr);
692                 if (ptr != map_pointer_)
693                 {
694                         Output("BUFFER_MAP_POINTER is %p should be %p.\n", ptr, map_pointer_);
695                         return ERROR;
696                 }
697                 return NO_ERROR;
698         }
699         void Data(GLsizeiptr size, const void* data, GLenum usage)
700         {
701                 size_  = size;
702                 usage_ = usage;
703                 glBufferData(GL_ATOMIC_COUNTER_BUFFER, size, data, usage);
704         }
705         void* MapRange(GLintptr offset, GLsizeiptr length, GLbitfield access)
706         {
707                 assert(mapped_ == GL_FALSE);
708
709                 map_pointer_ = glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, offset, length, access);
710                 if (map_pointer_)
711                 {
712                         map_offset_   = offset;
713                         map_length_   = length;
714                         access_flags_ = access;
715                         if (access & GL_MAP_READ_BIT)
716                                 access_ = GL_READ_ONLY;
717                         else if (access & GL_MAP_WRITE_BIT)
718                                 access_ = GL_WRITE_ONLY;
719                         mapped_         = GL_TRUE;
720                 }
721                 return map_pointer_;
722         }
723         GLboolean Unmap()
724         {
725                 assert(mapped_ == GL_TRUE);
726
727                 if (glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER))
728                 {
729                         map_offset_   = 0;
730                         map_length_   = 0;
731                         map_pointer_  = 0;
732                         mapped_           = GL_FALSE;
733                         access_           = GL_WRITE_ONLY;
734                         access_flags_ = 0;
735                         return GL_TRUE;
736                 }
737                 return GL_FALSE;
738         }
739
740 private:
741         GLuint  name_;
742         GLint64   size_;
743         GLenum  usage_;
744         GLenum  access_;
745         GLint    access_flags_;
746         GLboolean mapped_;
747         void*    map_pointer_;
748         GLint64   map_offset_;
749         GLint64   map_length_;
750 };
751 }
752
753 class BasicUsageCS : public SACSubcaseBase
754 {
755 public:
756         virtual std::string Title()
757         {
758                 return NL "Atomic Counters usage in the Compute Shader stage";
759         }
760         virtual std::string Purpose()
761         {
762                 return NL "Verify that atomic counters work as expected in the Compute Shader stage." NL
763                                   "In particular make sure that values returned by GLSL built-in functions" NL
764                                   "atomicCounterIncrement and atomicCounterDecrement are unique in every shader invocation." NL
765                                   "Also make sure that the final values in atomic counter buffer objects are as expected.";
766         }
767         virtual std::string Method()
768         {
769                 return NL "";
770         }
771         virtual std::string PassCriteria()
772         {
773                 return NL "";
774         }
775
776         GLuint counter_buffer_;
777         GLuint prog_;
778         GLuint m_buffer;
779
780         virtual long Setup()
781         {
782                 counter_buffer_ = 0;
783                 prog_                   = 0;
784                 m_buffer                = 0;
785                 return NO_ERROR;
786         }
787
788         GLuint CreateComputeProgram(const std::string& cs)
789         {
790                 const GLuint p = glCreateProgram();
791
792                 const char* const kGLSLVer = "#version 310 es\n";
793
794                 if (!cs.empty())
795                 {
796                         const GLuint sh = glCreateShader(GL_COMPUTE_SHADER);
797                         glAttachShader(p, sh);
798                         glDeleteShader(sh);
799                         const char* const src[2] = { kGLSLVer, cs.c_str() };
800                         glShaderSource(sh, 2, src, NULL);
801                         glCompileShader(sh);
802                 }
803
804                 return p;
805         }
806
807         bool CheckProgram(GLuint program, bool* compile_error = NULL)
808         {
809                 GLint compile_status = GL_TRUE;
810                 GLint status;
811                 glGetProgramiv(program, GL_LINK_STATUS, &status);
812
813                 if (status == GL_FALSE)
814                 {
815                         GLint attached_shaders;
816                         glGetProgramiv(program, GL_ATTACHED_SHADERS, &attached_shaders);
817
818                         if (attached_shaders > 0)
819                         {
820                                 std::vector<GLuint> shaders(attached_shaders);
821                                 glGetAttachedShaders(program, attached_shaders, NULL, &shaders[0]);
822
823                                 for (GLint i = 0; i < attached_shaders; ++i)
824                                 {
825                                         GLenum type;
826                                         glGetShaderiv(shaders[i], GL_SHADER_TYPE, reinterpret_cast<GLint*>(&type));
827                                         switch (type)
828                                         {
829                                         case GL_VERTEX_SHADER:
830                                                 Output("*** Vertex Shader ***\n");
831                                                 break;
832                                         case GL_TESS_CONTROL_SHADER:
833                                                 Output("*** Tessellation Control Shader ***\n");
834                                                 break;
835                                         case GL_TESS_EVALUATION_SHADER:
836                                                 Output("*** Tessellation Evaluation Shader ***\n");
837                                                 break;
838                                         case GL_GEOMETRY_SHADER:
839                                                 Output("*** Geometry Shader ***\n");
840                                                 break;
841                                         case GL_FRAGMENT_SHADER:
842                                                 Output("*** Fragment Shader ***\n");
843                                                 break;
844                                         case GL_COMPUTE_SHADER:
845                                                 Output("*** Compute Shader ***\n");
846                                                 break;
847                                         default:
848                                                 Output("*** Unknown Shader ***\n");
849                                                 break;
850                                         }
851
852                                         GLint res;
853                                         glGetShaderiv(shaders[i], GL_COMPILE_STATUS, &res);
854                                         if (res != GL_TRUE)
855                                                 compile_status = res;
856
857                                         // shader source
858                                         GLint length;
859                                         glGetShaderiv(shaders[i], GL_SHADER_SOURCE_LENGTH, &length);
860                                         if (length > 0)
861                                         {
862                                                 std::vector<GLchar> source(length);
863                                                 glGetShaderSource(shaders[i], length, NULL, &source[0]);
864                                                 Output("%s\n", &source[0]);
865                                         }
866
867                                         // shader info log
868                                         glGetShaderiv(shaders[i], GL_INFO_LOG_LENGTH, &length);
869                                         if (length > 0)
870                                         {
871                                                 std::vector<GLchar> log(length);
872                                                 glGetShaderInfoLog(shaders[i], length, NULL, &log[0]);
873                                                 Output("%s\n", &log[0]);
874                                         }
875                                 }
876                         }
877
878                         // program info log
879                         GLint length;
880                         glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
881                         if (length > 0)
882                         {
883                                 std::vector<GLchar> log(length);
884                                 glGetProgramInfoLog(program, length, NULL, &log[0]);
885                                 Output("%s\n", &log[0]);
886                         }
887                 }
888
889                 if (compile_error)
890                         *compile_error = (compile_status == GL_TRUE ? false : true);
891                 if (compile_status != GL_TRUE)
892                         return false;
893                 return status == GL_TRUE ? true : false;
894         }
895
896         virtual long Run()
897         {
898                 // create program
899                 const char* const glsl_cs = NL
900                         "layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;" NL
901                         "layout(binding = 0, offset = 0) uniform atomic_uint ac_counter_inc;" NL
902                         "layout(binding = 0, offset = 4) uniform atomic_uint ac_counter_dec;" NL "layout(std430) buffer Output {" NL
903                         "  mediump uint data_inc[256];" NL "  mediump uint data_dec[256];" NL "} g_out;" NL "void main() {" NL
904                         "  mediump uint offset = 32u * gl_GlobalInvocationID.y + gl_GlobalInvocationID.x;" NL
905                         "  g_out.data_inc[offset] = atomicCounterIncrement(ac_counter_inc);" NL
906                         "  g_out.data_dec[offset] = atomicCounterDecrement(ac_counter_dec);" NL "}";
907                 prog_ = CreateComputeProgram(glsl_cs);
908                 glLinkProgram(prog_);
909                 if (!CheckProgram(prog_))
910                         return ERROR;
911
912                 // create atomic counter buffer
913                 glGenBuffers(1, &counter_buffer_);
914                 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, counter_buffer_);
915                 glBufferData(GL_ATOMIC_COUNTER_BUFFER, 8, NULL, GL_DYNAMIC_COPY);
916                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
917
918                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, counter_buffer_);
919                 unsigned int* ptr = static_cast<unsigned int*>(
920                         glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, 8, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT));
921                 *ptr++ = 0;
922                 *ptr++ = 256;
923                 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
924
925                 glGenBuffers(1, &m_buffer);
926                 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
927                 glBufferData(GL_SHADER_STORAGE_BUFFER, 512 * sizeof(GLuint), NULL, GL_DYNAMIC_DRAW);
928                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
929
930                 glUseProgram(prog_);
931                 glDispatchCompute(4, 1, 1);
932
933                 long    error = NO_ERROR;
934                 GLuint* data;
935                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer);
936                 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
937                 data = static_cast<GLuint*>(
938                         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 512 * sizeof(GLuint), GL_MAP_READ_BIT | GL_MAP_WRITE_BIT));
939
940                 std::sort(data, data + 512);
941                 for (int i = 0; i < 512; i += 2)
942                 {
943                         if (data[i] != data[i + 1])
944                         {
945                                 Output("Pair of values should be equal, got: %d, %d\n", data[i], data[i + 1]);
946                                 error = ERROR;
947                         }
948                         if (i < 510 && data[i] == data[i + 2])
949                         {
950                                 Output("Too many same values found: %d, index: %d\n", data[i], i);
951                                 error = ERROR;
952                         }
953                 }
954
955                 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
956                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
957                 return error;
958         }
959
960         virtual long Cleanup()
961         {
962                 glDeleteBuffers(1, &counter_buffer_);
963                 glDeleteBuffers(1, &m_buffer);
964                 glDeleteProgram(prog_);
965                 glUseProgram(0);
966                 return NO_ERROR;
967         }
968 };
969
970 class BasicBufferOperations : public SACSubcaseBase
971 {
972         virtual std::string Title()
973         {
974                 return NL "Atomic Counter Buffer - basic operations";
975         }
976         virtual std::string Purpose()
977         {
978                 return NL
979                         "Verify that basic buffer operations work as expected with new buffer target." NL
980                         "Tested commands: BindBuffer, BufferData, BufferSubData, MapBuffer, MapBufferRange, UnmapBuffer and" NL
981                         "GetBufferSubData.";
982         }
983         virtual std::string Method()
984         {
985                 return NL "";
986         }
987         virtual std::string PassCriteria()
988         {
989                 return NL "";
990         }
991
992         GLuint buffer_;
993
994         virtual long Setup()
995         {
996                 buffer_ = 0;
997                 return NO_ERROR;
998         }
999         virtual long Run()
1000         {
1001                 glGenBuffers(1, &buffer_);
1002                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, buffer_);
1003                 glBufferData(GL_ATOMIC_COUNTER_BUFFER, 8 * 4, NULL, GL_STATIC_DRAW);
1004                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
1005
1006                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, buffer_);
1007                 GLuint* ptr = static_cast<GLuint*>(glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, 8 * 4, GL_MAP_WRITE_BIT));
1008                 if (ptr == NULL)
1009                 {
1010                         return ERROR;
1011                 }
1012                 for (GLuint i = 0; i < 8; ++i)
1013                         ptr[i]  = i;
1014                 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
1015                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
1016
1017                 long    res = NO_ERROR;
1018                 GLuint* data;
1019                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, buffer_);
1020                 data = static_cast<GLuint*>(glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, 32, GL_MAP_READ_BIT));
1021                 if (data == NULL)
1022                 {
1023                         return ERROR;
1024                 }
1025                 for (GLuint i = 0; i < 8; ++i)
1026                 {
1027                         if (data[i] != i)
1028                         {
1029                                 Output("data[%u] is: %u should be: %u\n", i, data[i], i);
1030                                 res = ERROR;
1031                         }
1032                 }
1033                 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
1034                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
1035                 if (res != NO_ERROR)
1036                         return res;
1037
1038                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, buffer_);
1039                 ptr = static_cast<GLuint*>(glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, 32, GL_MAP_WRITE_BIT));
1040                 if (ptr == NULL)
1041                 {
1042                         return ERROR;
1043                 }
1044                 for (GLuint i = 0; i < 8; ++i)
1045                         ptr[i]  = i * 2;
1046                 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
1047                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
1048
1049                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, buffer_);
1050                 data = static_cast<GLuint*>(glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, 32, GL_MAP_READ_BIT));
1051                 if (data == NULL)
1052                 {
1053                         return ERROR;
1054                 }
1055                 for (GLuint i = 0; i < 8; ++i)
1056                 {
1057                         if (data[i] != i * 2)
1058                         {
1059                                 Output("data[%u] is: %u should be: %u\n", i, data[i], i * 2);
1060                                 res = ERROR;
1061                         }
1062                 }
1063                 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
1064                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
1065
1066                 GLuint data2[8];
1067                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, buffer_);
1068                 for (GLuint i = 0; i < 8; ++i)
1069                         data2[i]  = i * 3;
1070                 glBufferSubData(GL_ATOMIC_COUNTER_BUFFER, 0, 32, data2);
1071                 for (GLuint i = 0; i < 8; ++i)
1072                         data2[i]  = 0;
1073                 data              = static_cast<GLuint*>(glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, 32, GL_MAP_READ_BIT));
1074                 for (GLuint i = 0; i < 8; ++i)
1075                 {
1076                         if (data[i] != i * 3)
1077                         {
1078                                 Output("data[%u] is: %u should be: %u\n", i, data[i], i * 3);
1079                                 res = ERROR;
1080                         }
1081                 }
1082                 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
1083                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
1084
1085                 return res;
1086         }
1087         virtual long Cleanup()
1088         {
1089                 glDeleteBuffers(1, &buffer_);
1090                 return NO_ERROR;
1091         }
1092 };
1093
1094 class BasicBufferState : public SACSubcaseBase
1095 {
1096         virtual std::string Title()
1097         {
1098                 return NL "Atomic Counter Buffer - state";
1099         }
1100         virtual std::string Purpose()
1101         {
1102                 return NL "Verify that setting and getting buffer state works as expected for new buffer target.";
1103         }
1104         virtual std::string Method()
1105         {
1106                 return NL "";
1107         }
1108         virtual std::string PassCriteria()
1109         {
1110                 return NL "";
1111         }
1112
1113         virtual long Run()
1114         {
1115                 Buffer buffer;
1116                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, buffer.name());
1117
1118                 if (buffer.Verify() != NO_ERROR)
1119                         return ERROR;
1120
1121                 buffer.Data(100, NULL, GL_DYNAMIC_COPY);
1122                 if (buffer.Verify() != NO_ERROR)
1123                         return ERROR;
1124
1125                 buffer.MapRange(10, 50, GL_MAP_WRITE_BIT);
1126                 if (buffer.Verify() != NO_ERROR)
1127                         return ERROR;
1128                 buffer.Unmap();
1129                 if (buffer.Verify() != NO_ERROR)
1130                         return ERROR;
1131
1132                 return NO_ERROR;
1133         }
1134 };
1135
1136 class BasicBufferBind : public SACSubcaseBase
1137 {
1138         virtual std::string Title()
1139         {
1140                 return NL "Atomic Counter Buffer - binding";
1141         }
1142         virtual std::string Purpose()
1143         {
1144                 return NL "Verify that binding buffer objects to ATOMIC_COUNTER_BUFFER (indexed) target" NL
1145                                   "works as expected. In particualr make sure that binding with BindBufferBase and BindBufferRange" NL
1146                                   "also bind to generic binding point and deleting buffer that is currently bound unbinds it. Tested" NL
1147                                   "commands: BindBuffer, BindBufferBase and BindBufferRange.";
1148         }
1149         virtual std::string Method()
1150         {
1151                 return NL "";
1152         }
1153         virtual std::string PassCriteria()
1154         {
1155                 return NL "";
1156         }
1157
1158         GLuint buffer_;
1159
1160         virtual long Setup()
1161         {
1162                 buffer_ = 0;
1163                 return NO_ERROR;
1164         }
1165         virtual long Run()
1166         {
1167                 GLint bindings;
1168                 glGetIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, &bindings);
1169                 Output("MAX_ATOMIC_COUNTER_BUFFER_BINDINGS: %d\n", bindings);
1170
1171                 if (!CheckGetCommands(GL_ATOMIC_COUNTER_BUFFER_BINDING, 0))
1172                         return ERROR;
1173                 for (GLint index = 0; index < bindings; ++index)
1174                 {
1175                         if (!CheckBufferBindingState(static_cast<GLuint>(index), 0, 0, 0))
1176                                 return ERROR;
1177                 }
1178
1179                 glGenBuffers(1, &buffer_);
1180                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, buffer_);
1181
1182                 if (!CheckGetCommands(GL_ATOMIC_COUNTER_BUFFER_BINDING, static_cast<GLint>(buffer_)))
1183                         return ERROR;
1184                 for (GLint index = 0; index < bindings; ++index)
1185                 {
1186                         if (!CheckBufferBindingState(static_cast<GLuint>(index), 0, 0, 0))
1187                                 return ERROR;
1188                 }
1189
1190                 long res = NO_ERROR;
1191
1192                 glBufferData(GL_ATOMIC_COUNTER_BUFFER, 1000, NULL, GL_DYNAMIC_COPY);
1193                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
1194
1195                 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, buffer_);
1196                 if (!CheckBufferBindingState(0, static_cast<GLint>(buffer_), 0, 1000))
1197                         res = ERROR;
1198                 if (!CheckGetCommands(GL_ATOMIC_COUNTER_BUFFER_BINDING, static_cast<GLint>(buffer_)))
1199                         res = ERROR;
1200
1201                 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, static_cast<GLuint>(bindings / 2), buffer_);
1202                 if (!CheckBufferBindingState(static_cast<GLuint>(bindings / 2), static_cast<GLint>(buffer_), 0, 1000))
1203                         res = ERROR;
1204
1205                 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, static_cast<GLuint>(bindings - 1), buffer_);
1206                 if (!CheckBufferBindingState(static_cast<GLuint>(bindings - 1), static_cast<GLint>(buffer_), 0, 1000))
1207                         res = ERROR;
1208                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
1209
1210                 glBindBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, buffer_, 8, 32);
1211                 if (!CheckBufferBindingState(0, static_cast<GLint>(buffer_), 8, 32))
1212                         res = ERROR;
1213                 if (!CheckGetCommands(GL_ATOMIC_COUNTER_BUFFER_BINDING, static_cast<GLint>(buffer_)))
1214                         res = ERROR;
1215
1216                 glBindBufferRange(GL_ATOMIC_COUNTER_BUFFER, static_cast<GLuint>(bindings / 2), buffer_, 512, 100);
1217                 if (!CheckBufferBindingState(static_cast<GLuint>(bindings / 2), static_cast<GLint>(buffer_), 512, 100))
1218                         res = ERROR;
1219
1220                 glBindBufferRange(GL_ATOMIC_COUNTER_BUFFER, static_cast<GLuint>(bindings - 1), buffer_, 12, 128);
1221                 if (!CheckBufferBindingState(static_cast<GLuint>(bindings - 1), static_cast<GLint>(buffer_), 12, 128))
1222                         res = ERROR;
1223
1224                 glDeleteBuffers(1, &buffer_);
1225                 buffer_ = 0;
1226
1227                 GLint i;
1228                 glGetIntegerv(GL_ATOMIC_COUNTER_BUFFER_BINDING, &i);
1229                 if (i != 0)
1230                 {
1231                         Output("Generic binding point should be 0 after deleting bound buffer object.\n");
1232                         res = ERROR;
1233                 }
1234                 for (GLint index = 0; index < bindings; ++index)
1235                 {
1236                         glGetIntegeri_v(GL_ATOMIC_COUNTER_BUFFER_BINDING, static_cast<GLuint>(index), &i);
1237                         if (i != 0)
1238                         {
1239                                 Output("Binding point %u should be 0 after deleting bound buffer object.\n", index);
1240                                 res = ERROR;
1241                         }
1242                 }
1243
1244                 return res;
1245         }
1246         virtual long Cleanup()
1247         {
1248                 glDeleteBuffers(1, &buffer_);
1249                 return NO_ERROR;
1250         }
1251 };
1252
1253 class BasicProgramMax : public SACSubcaseBase
1254 {
1255         virtual std::string Title()
1256         {
1257                 return NL "Program - max values";
1258         }
1259         virtual std::string Purpose()
1260         {
1261                 return NL "Verify all max values which deal with atomic counter buffers.";
1262         }
1263         virtual std::string Method()
1264         {
1265                 return NL "";
1266         }
1267         virtual std::string PassCriteria()
1268         {
1269                 return NL "";
1270         }
1271
1272         virtual long Run()
1273         {
1274                 if (!CheckMaxValue(GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, 1))
1275                         return ERROR;
1276                 if (!CheckMaxValue(GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE, 32))
1277                         return ERROR;
1278                 if (!CheckMaxValue(GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS, 1))
1279                         return ERROR;
1280                 if (!CheckMaxValue(GL_MAX_COMBINED_ATOMIC_COUNTERS, 8))
1281                         return ERROR;
1282                 if (!CheckMaxValue(GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS, 0))
1283                         return ERROR;
1284                 if (!CheckMaxValue(GL_MAX_VERTEX_ATOMIC_COUNTERS, 0))
1285                         return ERROR;
1286                 if (!CheckMaxValue(GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS, 1))
1287                         return ERROR;
1288                 if (!CheckMaxValue(GL_MAX_COMPUTE_ATOMIC_COUNTERS, 8))
1289                         return ERROR;
1290                 if (!CheckMaxValue(GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS, 0))
1291                         return ERROR;
1292                 if (!CheckMaxValue(GL_MAX_FRAGMENT_ATOMIC_COUNTERS, 0))
1293                         return ERROR;
1294                 return NO_ERROR;
1295         }
1296 };
1297
1298 class BasicProgramQuery : public BasicUsageCS
1299 {
1300         virtual std::string Title()
1301         {
1302                 return NL "Program - atomic counters queries";
1303         }
1304         virtual std::string Purpose()
1305         {
1306                 return NL "Get all the information from the program object about atomic counters." NL
1307                                   "Verify that all informations are correct. Tested commands:" NL
1308                                   "GetProgramiv and GetUniform* with new enums.";
1309         }
1310         virtual std::string Method()
1311         {
1312                 return NL "";
1313         }
1314         virtual std::string PassCriteria()
1315         {
1316                 return NL "";
1317         }
1318
1319         GLuint counter_buffer_, m_buffer;
1320         GLuint prog_;
1321
1322         virtual long Setup()
1323         {
1324                 counter_buffer_ = 0;
1325                 m_buffer                = 0;
1326                 prog_                   = 0;
1327                 return NO_ERROR;
1328         }
1329
1330         virtual long Run()
1331         {
1332
1333                 // create program
1334                 const char* glsl_cs =
1335                         NL "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;" NL "layout(std430) buffer Output {" NL
1336                            "  mediump vec4 data;" NL "} g_out;" NL
1337                            "layout(binding = 0, offset = 0)  uniform atomic_uint ac_counter0;" NL
1338                            "layout(binding = 0, offset = 4)  uniform atomic_uint ac_counter1;" NL
1339                            "layout(binding = 0)              uniform atomic_uint ac_counter2;" NL
1340                            "layout(binding = 0)              uniform atomic_uint ac_counter67[2];" NL
1341                            "layout(binding = 0)              uniform atomic_uint ac_counter3;" NL
1342                            "layout(binding = 0)              uniform atomic_uint ac_counter4;" NL
1343                            "layout(binding = 0)              uniform atomic_uint ac_counter5;" NL "void main() {" NL
1344                            "  mediump uint c = 0u;" NL "  c += atomicCounterIncrement(ac_counter0);" NL
1345                            "  c += atomicCounterIncrement(ac_counter1);" NL "  c += atomicCounterIncrement(ac_counter2);" NL
1346                            "  c += atomicCounterIncrement(ac_counter3);" NL "  c += atomicCounterIncrement(ac_counter4);" NL
1347                            "  c += atomicCounterIncrement(ac_counter5);" NL "  c += atomicCounterIncrement(ac_counter67[0]);" NL
1348                            "  c += atomicCounterIncrement(ac_counter67[1]);" NL
1349                            "  if (c > 10u) g_out.data = vec4(0.0, 1.0, 0.0, 1.0);" NL
1350                            "  else g_out.data = vec4(1.0, float(c), 0.0, 1.0);" NL "}";
1351
1352                 prog_ = CreateComputeProgram(glsl_cs);
1353                 glLinkProgram(prog_);
1354                 if (!CheckProgram(prog_))
1355                         return ERROR;
1356                 glUseProgram(prog_);
1357
1358                 // get active buffers
1359                 GLuint active_buffers;
1360                 glGetProgramiv(prog_, GL_ACTIVE_ATOMIC_COUNTER_BUFFERS, reinterpret_cast<GLint*>(&active_buffers));
1361                 if (active_buffers != 1)
1362                 {
1363                         Output("GL_ACTIVE_ATOMIC_COUNTER_BUFFERS is %u should be %d.\n", active_buffers, 1);
1364                         return ERROR;
1365                 }
1366
1367                 // get active uniforms
1368                 std::map<std::string, GLuint> uniforms_name_index;
1369                 GLuint active_uniforms;
1370                 glGetProgramiv(prog_, GL_ACTIVE_UNIFORMS, reinterpret_cast<GLint*>(&active_uniforms));
1371                 if (active_uniforms != 7)
1372                 {
1373                         Output("GL_ACTIVE_UNIFORMS is %u should be %d.\n", active_uniforms, 8);
1374                         return ERROR;
1375                 }
1376                 for (GLuint index = 0; index < active_uniforms; ++index)
1377                 {
1378                         GLchar name[32];
1379                         glGetProgramResourceName(prog_, GL_UNIFORM, index, sizeof(name), NULL, name);
1380                         uniforms_name_index.insert(std::make_pair(name, index));
1381                 }
1382
1383                 if (!CheckUniform(prog_, "ac_counter0", uniforms_name_index["ac_counter0"], GL_UNSIGNED_INT_ATOMIC_COUNTER, 1,
1384                                                   0, 0))
1385                         return ERROR;
1386                 if (!CheckUniform(prog_, "ac_counter1", uniforms_name_index["ac_counter1"], GL_UNSIGNED_INT_ATOMIC_COUNTER, 1,
1387                                                   4, 0))
1388                         return ERROR;
1389                 if (!CheckUniform(prog_, "ac_counter2", uniforms_name_index["ac_counter2"], GL_UNSIGNED_INT_ATOMIC_COUNTER, 1,
1390                                                   8, 0))
1391                         return ERROR;
1392                 if (!CheckUniform(prog_, "ac_counter3", uniforms_name_index["ac_counter3"], GL_UNSIGNED_INT_ATOMIC_COUNTER, 1,
1393                                                   20, 0))
1394                         return ERROR;
1395                 if (!CheckUniform(prog_, "ac_counter4", uniforms_name_index["ac_counter4"], GL_UNSIGNED_INT_ATOMIC_COUNTER, 1,
1396                                                   24, 0))
1397                         return ERROR;
1398                 if (!CheckUniform(prog_, "ac_counter5", uniforms_name_index["ac_counter5"], GL_UNSIGNED_INT_ATOMIC_COUNTER, 1,
1399                                                   28, 0))
1400                         return ERROR;
1401                 if (!CheckUniform(prog_, "ac_counter67[0]", uniforms_name_index["ac_counter67[0]"],
1402                                                   GL_UNSIGNED_INT_ATOMIC_COUNTER, 2, 12, 4))
1403                         return ERROR;
1404
1405                 // create atomic counter buffer
1406                 glGenBuffers(1, &counter_buffer_);
1407                 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, counter_buffer_);
1408                 const unsigned int data[8] = { 20, 20, 20, 20, 20, 20, 20, 20 };
1409                 glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(data), data, GL_DYNAMIC_DRAW);
1410                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
1411
1412                 glGenBuffers(1, &m_buffer);
1413                 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
1414                 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(Vec4), NULL, GL_DYNAMIC_DRAW);
1415                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
1416
1417                 glDispatchCompute(1, 1, 1);
1418
1419                 long  error = NO_ERROR;
1420                 Vec4* data_out;
1421                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer);
1422                 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT | GL_ATOMIC_COUNTER_BARRIER_BIT);
1423                 data_out = static_cast<Vec4*>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(Vec4), GL_MAP_READ_BIT));
1424                 if (data_out[0].x() != 0.0 || data_out[0].y() != 1.0 || data_out[0].z() != 0.0 || data_out[0].w() != 1.0)
1425                 {
1426                         Output("Expected vec4(0, 1, 0, 1) in the buffer, got: %f %f %f %f\n", data_out[0].x(), data_out[0].y(),
1427                                    data_out[0].z(), data_out[0].w());
1428                         error = ERROR;
1429                 }
1430                 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
1431                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
1432
1433                 return error;
1434         }
1435
1436         virtual long Cleanup()
1437         {
1438                 glDeleteBuffers(1, &counter_buffer_);
1439                 glDeleteBuffers(1, &m_buffer);
1440                 glDeleteProgram(prog_);
1441                 glUseProgram(0);
1442                 return NO_ERROR;
1443         }
1444 };
1445
1446 class BasicUsageSimple : public BasicUsageCS
1447 {
1448         virtual std::string Title()
1449         {
1450                 return NL "Simple Use Case";
1451         }
1452         virtual std::string Purpose()
1453         {
1454                 return NL "Verify that simple usage of atomic counters work as expected.";
1455         }
1456         virtual std::string Method()
1457         {
1458                 return NL "";
1459         }
1460         virtual std::string PassCriteria()
1461         {
1462                 return NL "";
1463         }
1464
1465         GLuint counter_buffer_;
1466         GLuint storage_buffer_;
1467         GLuint prog_;
1468
1469         virtual long Setup()
1470         {
1471                 counter_buffer_ = 0;
1472                 storage_buffer_ = 0;
1473                 prog_                   = 0;
1474                 return NO_ERROR;
1475         }
1476
1477         virtual long Run()
1478         {
1479                 const char* glsl_cs =
1480                         NL "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;" NL "layout(std430) buffer Output {" NL
1481                            "  mediump vec4 color;" NL "} g_out;" NL
1482                            "layout(binding = 0, offset = 0) uniform atomic_uint ac_counter;" NL "void main() {" NL
1483                            "  mediump uint c = atomicCounterIncrement(ac_counter);" NL
1484                            "  mediump float r = float(c / 40u) / 255.0;" NL "  g_out.color = vec4(r, 0.0, 0.0, 1.0);" NL "}";
1485                 prog_ = CreateComputeProgram(glsl_cs);
1486                 glLinkProgram(prog_);
1487                 if (!CheckProgram(prog_))
1488                         return ERROR;
1489
1490                 // create atomic counter buffer
1491                 glGenBuffers(1, &counter_buffer_);
1492                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, counter_buffer_);
1493                 glBufferData(GL_ATOMIC_COUNTER_BUFFER, 4, NULL, GL_DYNAMIC_COPY);
1494                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
1495
1496                 // clear counter buffer (set to 0)
1497                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, counter_buffer_);
1498                 unsigned int* ptr = static_cast<unsigned int*>(
1499                         glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, 4, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT));
1500                 *ptr = 0;
1501                 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
1502
1503                 // create shader storage buffer
1504                 glGenBuffers(1, &storage_buffer_);
1505                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, storage_buffer_);
1506                 glBufferData(GL_SHADER_STORAGE_BUFFER, 16, NULL, GL_DYNAMIC_DRAW);
1507                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
1508
1509                 glUseProgram(prog_);
1510                 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, counter_buffer_);
1511                 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, storage_buffer_);
1512                 glDispatchCompute(1, 1, 1);
1513
1514                 if (glGetError() != GL_NO_ERROR)
1515                 {
1516                         return ERROR;
1517                 }
1518                 else
1519                 {
1520                         return NO_ERROR;
1521                 }
1522         }
1523
1524         virtual long Cleanup()
1525         {
1526                 glDeleteBuffers(1, &counter_buffer_);
1527                 glDeleteBuffers(1, &storage_buffer_);
1528                 glDeleteProgram(prog_);
1529                 glUseProgram(0);
1530                 return NO_ERROR;
1531         }
1532 };
1533
1534 class BasicUsageFS : public SACSubcaseBase
1535 {
1536         virtual std::string Title()
1537         {
1538                 return NL "Atomic Counters usage in the Fragment Shader stage";
1539         }
1540         virtual std::string Purpose()
1541         {
1542                 return NL "Verify that atomic counters work as expected in the Fragment Shader stage." NL
1543                                   "In particular make sure that values returned by GLSL built-in functions" NL
1544                                   "atomicCounterIncrement and atomicCounterDecrement are unique in every shader invocation." NL
1545                                   "Also make sure that the final values in atomic counter buffer objects are as expected.";
1546         }
1547         virtual std::string Method()
1548         {
1549                 return NL "";
1550         }
1551         virtual std::string PassCriteria()
1552         {
1553                 return NL "";
1554         }
1555
1556         GLuint counter_buffer_;
1557         GLuint vao_, vbo_;
1558         GLuint prog_;
1559         GLuint fbo_, rt_[2];
1560
1561         virtual long Setup()
1562         {
1563                 counter_buffer_ = 0;
1564                 vao_ = vbo_ = 0;
1565                 prog_           = 0;
1566                 fbo_ = rt_[0] = rt_[1] = 0;
1567                 return NO_ERROR;
1568         }
1569         virtual long Run()
1570         {
1571
1572                 GLint p1, p2;
1573                 glGetIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS, &p1);
1574                 glGetIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTERS, &p2);
1575                 if (p1 < 1 || p2 < 2)
1576                 {
1577                         OutputNotSupported(
1578                                 "GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS or GL_MAX_FRAGMENT_ATOMIC_COUNTERS are less than required");
1579                         return NOT_SUPPORTED;
1580                 }
1581
1582                 // create program
1583                 const char* src_vs = "#version 310 es" NL "layout(location = 0) in vec4 i_vertex;" NL "void main() {" NL
1584                                                          "  gl_Position = i_vertex;" NL "}";
1585
1586                 const char* src_fs = "#version 310 es" NL "layout(location = 0) out uvec4 o_color[2];" NL
1587                                                          "layout(binding = 0, offset = 0) uniform atomic_uint ac_counter_inc;" NL
1588                                                          "layout(binding = 0, offset = 4) uniform atomic_uint ac_counter_dec;" NL "void main() {" NL
1589                                                          "  o_color[0] = uvec4(atomicCounterIncrement(ac_counter_inc));" NL
1590                                                          "  o_color[1] = uvec4(atomicCounterDecrement(ac_counter_dec));" NL "}";
1591                 prog_ = CreateProgram(src_vs, src_fs, true);
1592
1593                 // create atomic counter buffer
1594                 glGenBuffers(1, &counter_buffer_);
1595                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, counter_buffer_);
1596                 glBufferData(GL_ATOMIC_COUNTER_BUFFER, 8, NULL, GL_DYNAMIC_COPY);
1597                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
1598
1599                 // create render targets
1600                 const int s = 8;
1601                 glGenTextures(2, rt_);
1602
1603                 for (int i = 0; i < 2; ++i)
1604                 {
1605                         glBindTexture(GL_TEXTURE_2D, rt_[i]);
1606                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1607                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1608                         glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, s, s, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, NULL);
1609                         glBindTexture(GL_TEXTURE_2D, 0);
1610                 }
1611
1612                 // create fbo
1613                 glGenFramebuffers(1, &fbo_);
1614                 glBindFramebuffer(GL_FRAMEBUFFER, fbo_);
1615                 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt_[0], 0);
1616                 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, rt_[1], 0);
1617                 const GLenum draw_buffers[2] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
1618                 glDrawBuffers(2, draw_buffers);
1619                 glBindFramebuffer(GL_FRAMEBUFFER, 0);
1620
1621                 // create geometry
1622                 CreateQuad(&vao_, &vbo_, NULL);
1623
1624                 // init counter buffer
1625                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, counter_buffer_);
1626                 unsigned int* ptr = static_cast<unsigned int*>(
1627                         glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, 8, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT));
1628                 *ptr++ = 0;
1629                 *ptr++ = 80;
1630                 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
1631
1632                 // draw
1633                 glBindFramebuffer(GL_FRAMEBUFFER, fbo_);
1634                 glViewport(0, 0, s, s);
1635                 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, counter_buffer_);
1636                 glUseProgram(prog_);
1637                 glBindVertexArray(vao_);
1638                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1639
1640                 // validate
1641                 UVec4 data[s * s];
1642                 glReadBuffer(GL_COLOR_ATTACHMENT0);
1643                 glReadPixels(0, 0, s, s, GL_RGBA_INTEGER, GL_UNSIGNED_INT, data);
1644                 if (!CheckCounterValues(s * s, data, 0))
1645                         return ERROR;
1646
1647                 glReadBuffer(GL_COLOR_ATTACHMENT1);
1648                 glReadPixels(0, 0, s, s, GL_RGBA_INTEGER, GL_UNSIGNED_INT, data);
1649                 if (!CheckCounterValues(s * s, data, 16))
1650                         return ERROR;
1651
1652                 if (!CheckFinalCounterValue(counter_buffer_, 0, 64))
1653                         return ERROR;
1654                 if (!CheckFinalCounterValue(counter_buffer_, 4, 16))
1655                         return ERROR;
1656
1657                 return NO_ERROR;
1658         }
1659         virtual long Cleanup()
1660         {
1661                 glDeleteFramebuffers(1, &fbo_);
1662                 glDeleteTextures(2, rt_);
1663                 glViewport(0, 0, getWindowWidth(), getWindowHeight());
1664                 glDeleteBuffers(1, &counter_buffer_);
1665                 glDeleteVertexArrays(1, &vao_);
1666                 glDeleteBuffers(1, &vbo_);
1667                 glDeleteProgram(prog_);
1668                 glUseProgram(0);
1669                 return NO_ERROR;
1670         }
1671 };
1672
1673 class BasicUsageVS : public SACSubcaseBase
1674 {
1675         virtual std::string Title()
1676         {
1677                 return NL "Atomic Counters usage in the Vertex Shader stage";
1678         }
1679         virtual std::string Purpose()
1680         {
1681                 return NL "Verify that atomic counters work as expected in the Vertex Shader stage." NL
1682                                   "In particular make sure that values returned by GLSL built-in functions" NL
1683                                   "atomicCounterIncrement and atomicCounterDecrement are unique in every shader invocation." NL
1684                                   "Also make sure that the final values in atomic counter buffer objects are as expected.";
1685         }
1686         virtual std::string Method()
1687         {
1688                 return NL "";
1689         }
1690         virtual std::string PassCriteria()
1691         {
1692                 return NL "";
1693         }
1694
1695         GLuint counter_buffer_[2];
1696         GLuint xfb_buffer_[2];
1697         GLuint array_buffer_;
1698         GLuint vao_;
1699         GLuint prog_;
1700
1701         virtual long Setup()
1702         {
1703                 counter_buffer_[0] = counter_buffer_[1] = 0;
1704                 xfb_buffer_[0] = xfb_buffer_[1] = 0;
1705                 array_buffer_                                   = 0;
1706                 vao_                                                    = 0;
1707                 prog_                                                   = 0;
1708                 return NO_ERROR;
1709         }
1710         virtual long Run()
1711         {
1712
1713                 GLint p1, p2;
1714                 glGetIntegerv(GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS, &p1);
1715                 glGetIntegerv(GL_MAX_VERTEX_ATOMIC_COUNTERS, &p2);
1716                 if (p1 < 2 || p2 < 2)
1717                 {
1718                         OutputNotSupported(
1719                                 "GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS or GL_MAX_VERTEX_ATOMIC_COUNTERS are less than required");
1720                         return NOT_SUPPORTED;
1721                 }
1722
1723                 // create program
1724                 const char* src_vs =
1725                         "#version 310 es" NL "layout(location = 0) in uint i_zero;" NL "flat out uint o_atomic_inc;" NL
1726                         "flat out uint o_atomic_dec;" NL "layout(binding = 0, offset = 0) uniform atomic_uint ac_counter_inc;" NL
1727                         "layout(binding = 1, offset = 0) uniform atomic_uint ac_counter_dec;" NL "void main() {" NL
1728                         "  o_atomic_inc = i_zero + atomicCounterIncrement(ac_counter_inc);" NL
1729                         "  o_atomic_dec = i_zero + atomicCounterDecrement(ac_counter_dec);" NL "}";
1730
1731                 const char* src_fs = "#version 310 es                \n"
1732                                                          "out mediump vec4 color;        \n"
1733                                                          "void main() {                  \n"
1734                                                          "    color = vec4(0, 1, 0, 1);  \n"
1735                                                          "}";
1736
1737                 prog_                              = CreateProgram(src_vs, src_fs, false);
1738                 const char* xfb_var[2] = { "o_atomic_inc", "o_atomic_dec" };
1739                 glTransformFeedbackVaryings(prog_, 2, xfb_var, GL_SEPARATE_ATTRIBS);
1740                 LinkProgram(prog_);
1741
1742                 // create array buffer
1743                 const unsigned int array_buffer_data[32] = { 0 };
1744                 glGenBuffers(1, &array_buffer_);
1745                 glBindBuffer(GL_ARRAY_BUFFER, array_buffer_);
1746                 glBufferData(GL_ARRAY_BUFFER, sizeof(array_buffer_data), array_buffer_data, GL_STATIC_DRAW);
1747                 glBindBuffer(GL_ARRAY_BUFFER, 0);
1748
1749                 // create atomic counter buffers
1750                 glGenBuffers(2, counter_buffer_);
1751                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, counter_buffer_[0]);
1752                 glBufferData(GL_ATOMIC_COUNTER_BUFFER, 4, NULL, GL_DYNAMIC_COPY);
1753                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, counter_buffer_[1]);
1754                 glBufferData(GL_ATOMIC_COUNTER_BUFFER, 4, NULL, GL_DYNAMIC_COPY);
1755                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
1756
1757                 // create transform feedback buffers
1758                 glGenBuffers(2, xfb_buffer_);
1759                 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_buffer_[0]);
1760                 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 1000, NULL, GL_STREAM_COPY);
1761                 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_buffer_[1]);
1762                 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 1000, NULL, GL_STREAM_COPY);
1763                 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
1764
1765                 // init counter buffers
1766                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, counter_buffer_[0]);
1767                 unsigned int* ptr = static_cast<unsigned int*>(
1768                         glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, 4, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT));
1769                 *ptr = 7;
1770                 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
1771
1772                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, counter_buffer_[1]);
1773                 ptr = static_cast<unsigned int*>(
1774                         glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, 4, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT));
1775                 *ptr = 77;
1776                 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
1777
1778                 // create vertex array object
1779                 glGenVertexArrays(1, &vao_);
1780                 glBindVertexArray(vao_);
1781                 glBindBuffer(GL_ARRAY_BUFFER, array_buffer_);
1782                 glVertexAttribIPointer(0, 1, GL_UNSIGNED_INT, 0, 0);
1783                 glBindBuffer(GL_ARRAY_BUFFER, 0);
1784                 glEnableVertexAttribArray(0);
1785                 glBindVertexArray(0);
1786
1787                 // draw
1788                 glEnable(GL_RASTERIZER_DISCARD);
1789                 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, counter_buffer_[0]);
1790                 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 1, counter_buffer_[1]);
1791                 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, xfb_buffer_[0]);
1792                 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 1, xfb_buffer_[1]);
1793                 glUseProgram(prog_);
1794                 glBindVertexArray(vao_);
1795                 glBeginTransformFeedback(GL_POINTS);
1796                 glDrawArrays(GL_POINTS, 0, 32);
1797                 glEndTransformFeedback();
1798                 glDisable(GL_RASTERIZER_DISCARD);
1799
1800                 // validate
1801                 GLuint* data;
1802                 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_buffer_[0]);
1803                 // CheckCounterValues will sort in place, so map buffer for both read and write
1804                 data = static_cast<GLuint*>(
1805                         glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 32 * 4, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT));
1806                 if (!CheckCounterValues(32, data, 7))
1807                         return ERROR;
1808                 glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
1809                 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
1810
1811                 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_buffer_[1]);
1812                 data = static_cast<GLuint*>(
1813                         glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 32 * 4, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT));
1814                 if (!CheckCounterValues(32, data, 45))
1815                         return ERROR;
1816                 glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
1817                 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
1818
1819                 if (!CheckFinalCounterValue(counter_buffer_[0], 0, 39))
1820                         return ERROR;
1821                 if (!CheckFinalCounterValue(counter_buffer_[1], 0, 45))
1822                         return ERROR;
1823
1824                 return NO_ERROR;
1825         }
1826         virtual long Cleanup()
1827         {
1828                 glDeleteBuffers(2, counter_buffer_);
1829                 glDeleteBuffers(2, xfb_buffer_);
1830                 glDeleteBuffers(1, &array_buffer_);
1831                 glDeleteVertexArrays(1, &vao_);
1832                 glDeleteProgram(prog_);
1833                 glUseProgram(0);
1834                 return NO_ERROR;
1835         }
1836 };
1837
1838 class AdvancedUsageMultiStage : public SACSubcaseBase
1839 {
1840         virtual std::string Title()
1841         {
1842                 return NL "Same atomic counter accessed from multiple shader stages";
1843         }
1844         virtual std::string Purpose()
1845         {
1846                 return NL "Same atomic counter is incremented (decremented) from two shader stages (VS and FS)." NL
1847                                   "Verify that this scenario works as expected. In particular ensure that all generated values are "
1848                                   "unique and" NL "final value in atomic counter buffer objects are as expected.";
1849         }
1850         virtual std::string Method()
1851         {
1852                 return NL "";
1853         }
1854         virtual std::string PassCriteria()
1855         {
1856                 return NL "";
1857         }
1858
1859         GLuint counter_buffer_;
1860         GLuint xfb_buffer_[2];
1861         GLuint vao_, vbo_;
1862         GLuint prog_;
1863         GLuint fbo_, rt_[2];
1864
1865         virtual long Setup()
1866         {
1867                 counter_buffer_ = 0;
1868                 xfb_buffer_[0] = xfb_buffer_[1] = 0;
1869                 vao_ = vbo_ = 0;
1870                 prog_           = 0;
1871                 fbo_ = rt_[0] = rt_[1] = 0;
1872                 return NO_ERROR;
1873         }
1874         virtual long Run()
1875         {
1876
1877                 GLint p1, p2, p3, p4;
1878                 glGetIntegerv(GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS, &p1);
1879                 glGetIntegerv(GL_MAX_VERTEX_ATOMIC_COUNTERS, &p2);
1880                 glGetIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS, &p3);
1881                 glGetIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTERS, &p4);
1882                 if (p1 < 8 || p2 < 2 || p3 < 8 || p4 < 2)
1883                 {
1884                         OutputNotSupported("GL_MAX_FRAGMENT/VERTEX_ATOMIC_COUNTER_BUFFERS or"
1885                                                            "GL_MAX_FRAGMENT/VERTEX_ATOMIC_COUNTERS are less than required");
1886                         return NOT_SUPPORTED;
1887                 }
1888
1889                 // create program
1890                 const char* src_vs =
1891                         "#version 310 es" NL "layout(location = 0) in vec4 i_vertex;" NL "flat out uint o_atomic_inc;" NL
1892                         "flat out uint o_atomic_dec;" NL "layout(binding = 1, offset = 16) uniform atomic_uint ac_counter_inc;" NL
1893                         "layout(binding = 7, offset = 128) uniform atomic_uint ac_counter_dec;" NL "void main() {" NL
1894                         "  gl_Position = i_vertex;" NL "  o_atomic_inc = atomicCounterIncrement(ac_counter_inc);" NL
1895                         "  o_atomic_dec = atomicCounterDecrement(ac_counter_dec);" NL "}";
1896                 const char* src_fs = "#version 310 es" NL "layout(location = 0) out uvec4 o_color[2];" NL
1897                                                          "layout(binding = 1, offset = 16) uniform atomic_uint ac_counter_inc;" NL
1898                                                          "layout(binding = 7, offset = 128) uniform atomic_uint ac_counter_dec;" NL
1899                                                          "void main() {" NL "  o_color[0] = uvec4(atomicCounterIncrement(ac_counter_inc));" NL
1900                                                          "  o_color[1] = uvec4(atomicCounterDecrement(ac_counter_dec));" NL "}";
1901                 prog_                              = CreateProgram(src_vs, src_fs, false);
1902                 const char* xfb_var[2] = { "o_atomic_inc", "o_atomic_dec" };
1903                 glTransformFeedbackVaryings(prog_, 2, xfb_var, GL_SEPARATE_ATTRIBS);
1904                 LinkProgram(prog_);
1905
1906                 // create atomic counter buffer
1907                 std::vector<GLuint> init_data(256, 100);
1908                 glGenBuffers(1, &counter_buffer_);
1909                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, counter_buffer_);
1910                 glBufferData(GL_ATOMIC_COUNTER_BUFFER, (GLsizeiptr)(init_data.size() * sizeof(GLuint)), &init_data[0],
1911                                          GL_DYNAMIC_COPY);
1912                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
1913
1914                 // create transform feedback buffers
1915                 glGenBuffers(2, xfb_buffer_);
1916                 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_buffer_[0]);
1917                 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 1000, NULL, GL_STREAM_COPY);
1918                 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_buffer_[1]);
1919                 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 1000, NULL, GL_STREAM_COPY);
1920                 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
1921
1922                 // create render targets
1923                 const int s = 8;
1924                 glGenTextures(2, rt_);
1925                 for (int i = 0; i < 2; ++i)
1926                 {
1927                         glBindTexture(GL_TEXTURE_2D, rt_[i]);
1928                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1929                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1930                         glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, s, s, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, NULL);
1931                         glBindTexture(GL_TEXTURE_2D, 0);
1932                 }
1933
1934                 // create fbo
1935                 glGenFramebuffers(1, &fbo_);
1936                 glBindFramebuffer(GL_FRAMEBUFFER, fbo_);
1937                 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt_[0], 0);
1938                 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, rt_[1], 0);
1939                 const GLenum draw_buffers[2] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
1940                 glDrawBuffers(2, draw_buffers);
1941                 glBindFramebuffer(GL_FRAMEBUFFER, 0);
1942
1943                 // create geometry
1944                 CreateTriangle(&vao_, &vbo_, NULL);
1945
1946                 // draw
1947                 glBindBufferRange(GL_ATOMIC_COUNTER_BUFFER, 1, counter_buffer_, 16, 32);
1948                 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 7, counter_buffer_);
1949                 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, xfb_buffer_[0]);
1950                 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 1, xfb_buffer_[1]);
1951                 glBindFramebuffer(GL_FRAMEBUFFER, fbo_);
1952                 glViewport(0, 0, s, s);
1953                 glUseProgram(prog_);
1954                 glBindVertexArray(vao_);
1955                 glBeginTransformFeedback(GL_TRIANGLES);
1956                 glDrawArrays(GL_TRIANGLES, 0, 3);
1957                 glEndTransformFeedback();
1958
1959                 // validate
1960                 UVec4 data[s * s + 3];
1961                 glReadBuffer(GL_COLOR_ATTACHMENT0);
1962                 glReadPixels(0, 0, s, s, GL_RGBA_INTEGER, GL_UNSIGNED_INT, data);
1963                 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_buffer_[0]);
1964                 GLuint* data2;
1965                 data2 = static_cast<GLuint*>(
1966                         glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 3 * sizeof(GLuint), GL_MAP_READ_BIT));
1967                 data[s * s]             = UVec4(data2[0]);
1968                 data[s * s + 1] = UVec4(data2[1]);
1969                 data[s * s + 2] = UVec4(data2[2]);
1970                 if (!CheckCounterValues(s * s + 3, data, 100))
1971                         return ERROR;
1972                 glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
1973                 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
1974
1975                 glReadBuffer(GL_COLOR_ATTACHMENT1);
1976                 glReadPixels(0, 0, s, s, GL_RGBA_INTEGER, GL_UNSIGNED_INT, data);
1977                 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_buffer_[1]);
1978                 data2 = static_cast<GLuint*>(
1979                         glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 3 * sizeof(GLuint), GL_MAP_READ_BIT));
1980                 data[s * s]             = UVec4(data2[0]);
1981                 data[s * s + 1] = UVec4(data2[1]);
1982                 data[s * s + 2] = UVec4(data2[2]);
1983                 if (!CheckCounterValues(s * s + 3, data, 33))
1984                         return ERROR;
1985                 glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
1986                 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
1987
1988                 if (!CheckFinalCounterValue(counter_buffer_, 32, 167))
1989                         return ERROR;
1990                 if (!CheckFinalCounterValue(counter_buffer_, 128, 33))
1991                         return ERROR;
1992
1993                 return NO_ERROR;
1994         }
1995         virtual long Cleanup()
1996         {
1997                 glDeleteFramebuffers(1, &fbo_);
1998                 glDeleteTextures(2, rt_);
1999                 glViewport(0, 0, getWindowWidth(), getWindowHeight());
2000                 glDeleteBuffers(1, &counter_buffer_);
2001                 glDeleteBuffers(2, xfb_buffer_);
2002                 glDeleteVertexArrays(1, &vao_);
2003                 glDeleteBuffers(1, &vbo_);
2004                 glDeleteProgram(prog_);
2005                 glUseProgram(0);
2006                 return NO_ERROR;
2007         }
2008 };
2009
2010 class AdvancedUsageDrawUpdateDraw : public SACSubcaseBase
2011 {
2012         virtual std::string Title()
2013         {
2014                 return NL "Update via Draw Call and update via MapBufferRange";
2015         }
2016         virtual std::string Purpose()
2017         {
2018                 return NL "1. Create atomic counter buffers and init them with start values." NL
2019                                   "2. Increment (decrement) buffer values in the shader." NL
2020                                   "3. Map buffers with MapBufferRange command. Increment (decrement) buffer values manually." NL
2021                                   "4. Unmap buffers with UnmapBuffer command." NL
2022                                   "5. Again increment (decrement) buffer values in the shader." NL
2023                                   "Verify that this scenario works as expected and final values in the buffer objects are correct.";
2024         }
2025         virtual std::string Method()
2026         {
2027                 return NL "";
2028         }
2029         virtual std::string PassCriteria()
2030         {
2031                 return NL "";
2032         }
2033
2034         GLuint counter_buffer_;
2035         GLuint vao_, vbo_;
2036         GLuint prog_, prog2_;
2037         GLuint fbo_, rt_[2];
2038
2039         virtual long Setup()
2040         {
2041                 counter_buffer_ = 0;
2042                 vao_ = vbo_ = 0;
2043                 prog_           = 0;
2044                 prog2_          = 0;
2045                 fbo_ = rt_[0] = rt_[1] = 0;
2046                 return NO_ERROR;
2047         }
2048         virtual long Run()
2049         {
2050
2051                 GLint p1, p2;
2052                 glGetIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS, &p1);
2053                 glGetIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTERS, &p2);
2054                 if (p1 < 1 || p2 < 2)
2055                 {
2056                         OutputNotSupported(
2057                                 "GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS or GL_MAX_FRAGMENT_ATOMIC_COUNTERS are less than required");
2058                         return NOT_SUPPORTED;
2059                 }
2060
2061                 // create program
2062                 const char* src_vs = "#version 310 es" NL "layout(location = 0) in vec4 i_vertex;" NL "void main() {" NL
2063                                                          "  gl_Position = i_vertex;" NL "}";
2064                 const char* src_fs = "#version 310 es" NL "layout(location = 0) out uvec4 o_color[2];" NL
2065                                                          "layout(binding = 0) uniform atomic_uint ac_counter[2];" NL "void main() {" NL
2066                                                          "  o_color[0] = uvec4(atomicCounterIncrement(ac_counter[0]));" NL
2067                                                          "  o_color[1] = uvec4(atomicCounterDecrement(ac_counter[1]));" NL "}";
2068                 const char* src_fs2 = "#version 310 es" NL "layout(location = 0) out uvec4 o_color[2];" NL
2069                                                           "layout(binding = 0) uniform atomic_uint ac_counter[2];" NL "void main() {" NL
2070                                                           "  o_color[0] = uvec4(atomicCounter(ac_counter[0]));" NL
2071                                                           "  o_color[1] = uvec4(atomicCounter(ac_counter[1]));" NL "}";
2072                 prog_  = CreateProgram(src_vs, src_fs, true);
2073                 prog2_ = CreateProgram(src_vs, src_fs2, true);
2074
2075                 // create atomic counter buffer
2076                 glGenBuffers(1, &counter_buffer_);
2077                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, counter_buffer_);
2078                 glBufferData(GL_ATOMIC_COUNTER_BUFFER, 8, NULL, GL_DYNAMIC_COPY);
2079                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
2080
2081                 // create render targets
2082                 const int s = 8;
2083                 glGenTextures(2, rt_);
2084
2085                 for (int i = 0; i < 2; ++i)
2086                 {
2087                         glBindTexture(GL_TEXTURE_2D, rt_[i]);
2088                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2089                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2090                         glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, s, s, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, NULL);
2091                         glBindTexture(GL_TEXTURE_2D, 0);
2092                 }
2093
2094                 // create fbo
2095                 glGenFramebuffers(1, &fbo_);
2096                 glBindFramebuffer(GL_FRAMEBUFFER, fbo_);
2097                 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt_[0], 0);
2098                 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, rt_[1], 0);
2099                 const GLenum draw_buffers[2] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
2100                 glDrawBuffers(2, draw_buffers);
2101                 glBindFramebuffer(GL_FRAMEBUFFER, 0);
2102
2103                 // create geometry
2104                 CreateQuad(&vao_, &vbo_, NULL);
2105
2106                 // init counter buffer
2107                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, counter_buffer_);
2108                 unsigned int* ptr = static_cast<unsigned int*>(
2109                         glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, 8, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT));
2110                 *ptr++ = 256;
2111                 *ptr++ = 256;
2112                 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
2113
2114                 // draw
2115                 glBindFramebuffer(GL_FRAMEBUFFER, fbo_);
2116                 glViewport(0, 0, s, s);
2117                 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, counter_buffer_);
2118                 glUseProgram(prog_);
2119                 glBindVertexArray(vao_);
2120                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2121
2122                 // update counter buffer
2123                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, counter_buffer_);
2124                 ptr = static_cast<unsigned int*>(
2125                         glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, 8, GL_MAP_WRITE_BIT | GL_MAP_READ_BIT));
2126                 *ptr++ += 512;
2127                 *ptr++ += 1024;
2128                 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
2129
2130                 // draw
2131                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2132                 glMemoryBarrier(GL_ATOMIC_COUNTER_BARRIER_BIT);
2133
2134                 // draw
2135                 glUseProgram(prog2_);
2136                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2137
2138                 // validate
2139                 UVec4 data[s * s];
2140                 glReadBuffer(GL_COLOR_ATTACHMENT0);
2141                 glReadPixels(0, 0, s, s, GL_RGBA_INTEGER, GL_UNSIGNED_INT, data);
2142                 for (int i = 0; i < s * s; ++i)
2143                 {
2144                         if (data[i].x() != 896)
2145                         {
2146                                 Output("Counter value is %u should be %u.\n", data[i].x(), 896);
2147                                 return ERROR;
2148                         }
2149                 }
2150
2151                 glReadBuffer(GL_COLOR_ATTACHMENT1);
2152                 glReadPixels(0, 0, s, s, GL_RGBA_INTEGER, GL_UNSIGNED_INT, data);
2153                 for (int i = 0; i < s * s; ++i)
2154                 {
2155                         if (data[i].x() != 1152)
2156                         {
2157                                 Output("Counter value is %u should be %u.\n", data[i].x(), 896);
2158                                 return ERROR;
2159                         }
2160                 }
2161
2162                 if (!CheckFinalCounterValue(counter_buffer_, 0, 896))
2163                         return ERROR;
2164                 if (!CheckFinalCounterValue(counter_buffer_, 4, 1152))
2165                         return ERROR;
2166
2167                 return NO_ERROR;
2168         }
2169         virtual long Cleanup()
2170         {
2171                 glDeleteFramebuffers(1, &fbo_);
2172                 glDeleteTextures(2, rt_);
2173                 glViewport(0, 0, getWindowWidth(), getWindowHeight());
2174                 glDeleteBuffers(1, &counter_buffer_);
2175                 glDeleteVertexArrays(1, &vao_);
2176                 glDeleteBuffers(1, &vbo_);
2177                 glDeleteProgram(prog_);
2178                 glDeleteProgram(prog2_);
2179                 glUseProgram(0);
2180                 return NO_ERROR;
2181         }
2182 };
2183
2184 class AdvancedUsageManyCounters : public BasicUsageCS
2185 {
2186         virtual std::string Title()
2187         {
2188                 return NL "Large atomic counters array indexed with uniforms";
2189         }
2190         virtual std::string Purpose()
2191         {
2192                 return NL "Verify that large atomic counters array works as expected when indexed with dynamically uniform "
2193                                   "expressions." NL
2194                                   "Built-ins tested: atomicCounterIncrement, atomicCounterDecrement and atomicCounter.";
2195         }
2196         virtual std::string Method()
2197         {
2198                 return NL "";
2199         }
2200         virtual std::string PassCriteria()
2201         {
2202                 return NL "";
2203         }
2204
2205         GLuint counter_buffer_, m_ssbo;
2206         GLuint prog_;
2207
2208         virtual long Setup()
2209         {
2210                 counter_buffer_ = 0;
2211                 m_ssbo                  = 0;
2212                 prog_                   = 0;
2213                 return NO_ERROR;
2214         }
2215
2216         virtual long Run()
2217         {
2218                 // create program
2219                 const char* glsl_cs = NL
2220                         "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;" NL "layout(std430) buffer Output {" NL
2221                         "  mediump uvec4 data1[64];" NL "  mediump uvec4 data2[64];" NL "  mediump uvec4 data3[64];" NL
2222                         "  mediump uvec4 data4[64];" NL "  mediump uvec4 data5[64];" NL "  mediump uvec4 data6[64];" NL
2223                         "  mediump uvec4 data7[64];" NL "  mediump uvec4 data8[64];" NL "} g_out;" NL
2224                         "uniform mediump int u_active_counters[8];" NL "layout(binding = 0) uniform atomic_uint ac_counter[8];" NL
2225                         "void main() {" NL "  mediump uint offset = 8u * gl_GlobalInvocationID.y + gl_GlobalInvocationID.x;" NL
2226                         "  g_out.data1[offset] = uvec4(atomicCounterIncrement(ac_counter[u_active_counters[0]]));" NL
2227                         "  g_out.data2[offset] = uvec4(atomicCounterDecrement(ac_counter[u_active_counters[1]]));" NL
2228                         "  g_out.data3[offset] = uvec4(atomicCounter(ac_counter[u_active_counters[2]]));" NL
2229                         "  g_out.data4[offset] = uvec4(atomicCounterIncrement(ac_counter[u_active_counters[3]]));" NL
2230                         "  g_out.data5[offset] = uvec4(atomicCounterDecrement(ac_counter[u_active_counters[4]]));" NL
2231                         "  g_out.data6[offset] = uvec4(atomicCounter(ac_counter[u_active_counters[5]]));" NL
2232                         "  g_out.data7[offset] = uvec4(atomicCounterIncrement(ac_counter[u_active_counters[6]]));" NL
2233                         "  g_out.data8[offset] = uvec4(atomicCounterIncrement(ac_counter[u_active_counters[7]]));" NL "}";
2234
2235                 prog_ = CreateComputeProgram(glsl_cs);
2236                 glLinkProgram(prog_);
2237                 if (!CheckProgram(prog_))
2238                         return ERROR;
2239
2240                 // create atomic counter buffer
2241                 std::vector<GLuint> init_data(1024, 1000);
2242                 glGenBuffers(1, &counter_buffer_);
2243                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, counter_buffer_);
2244                 glBufferData(GL_ATOMIC_COUNTER_BUFFER, 1024 * sizeof(GLuint), &init_data[0], GL_DYNAMIC_COPY);
2245                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
2246
2247                 glGenBuffers(1, &m_ssbo);
2248                 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_ssbo);
2249                 glBufferData(GL_SHADER_STORAGE_BUFFER, 8 * 64 * sizeof(UVec4), NULL, GL_DYNAMIC_DRAW);
2250                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
2251
2252                 // set uniforms
2253                 glUseProgram(prog_);
2254                 glUniform1i(glGetUniformLocation(prog_, "u_active_counters[0]"), 0);
2255                 glUniform1i(glGetUniformLocation(prog_, "u_active_counters[1]"), 1);
2256                 glUniform1i(glGetUniformLocation(prog_, "u_active_counters[2]"), 2);
2257                 glUniform1i(glGetUniformLocation(prog_, "u_active_counters[3]"), 3);
2258                 glUniform1i(glGetUniformLocation(prog_, "u_active_counters[4]"), 4);
2259                 glUniform1i(glGetUniformLocation(prog_, "u_active_counters[5]"), 5);
2260                 glUniform1i(glGetUniformLocation(prog_, "u_active_counters[6]"), 6);
2261                 glUniform1i(glGetUniformLocation(prog_, "u_active_counters[7]"), 7);
2262
2263                 // dispatch
2264                 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, counter_buffer_);
2265                 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_ssbo);
2266                 glDispatchCompute(8, 8, 1);
2267
2268                 // validate
2269                 glMemoryBarrier(GL_ATOMIC_COUNTER_BARRIER_BIT | GL_SHADER_STORAGE_BARRIER_BIT);
2270                 UVec4* data;
2271                 long   error = NO_ERROR;
2272
2273                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_ssbo);
2274                 data = static_cast<UVec4*>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 64 * sizeof(UVec4), GL_MAP_READ_BIT));
2275                 if (!CheckCounterValues(8 * 8, data, 1000))
2276                         error = ERROR;
2277                 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2278                 if (!CheckFinalCounterValue(counter_buffer_, 0, 1064))
2279                         error = ERROR;
2280
2281                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_ssbo);
2282                 data = static_cast<UVec4*>(
2283                         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 64 * sizeof(UVec4), 64 * sizeof(UVec4), GL_MAP_READ_BIT));
2284                 if (!CheckCounterValues(8 * 8, data, 1000 - 64))
2285                         error = ERROR;
2286                 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2287                 if (!CheckFinalCounterValue(counter_buffer_, 1 * sizeof(GLuint), 1000 - 64))
2288                         error = ERROR;
2289
2290                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_ssbo);
2291                 data = static_cast<UVec4*>(
2292                         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 64 * sizeof(UVec4) * 2, 64 * sizeof(UVec4), GL_MAP_READ_BIT));
2293                 for (int i = 0; i < 8 * 8; ++i)
2294                         if (data[i].x() != 1000)
2295                                 error = ERROR;
2296                 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2297                 if (!CheckFinalCounterValue(counter_buffer_, 2 * sizeof(GLuint), 1000))
2298                         error = ERROR;
2299
2300                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_ssbo);
2301                 data = static_cast<UVec4*>(
2302                         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 64 * sizeof(UVec4) * 3, 64 * sizeof(UVec4), GL_MAP_READ_BIT));
2303                 if (!CheckCounterValues(8 * 8, data, 1000))
2304                         error = ERROR;
2305                 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2306                 if (!CheckFinalCounterValue(counter_buffer_, 3 * sizeof(GLuint), 1064))
2307                         error = ERROR;
2308
2309                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_ssbo);
2310                 data = static_cast<UVec4*>(
2311                         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 64 * sizeof(UVec4) * 4, 64 * sizeof(UVec4), GL_MAP_READ_BIT));
2312                 if (!CheckCounterValues(8 * 8, data, 1000 - 64))
2313                         error = ERROR;
2314                 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2315                 if (!CheckFinalCounterValue(counter_buffer_, 4 * sizeof(GLuint), 1000 - 64))
2316                         error = ERROR;
2317
2318                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_ssbo);
2319                 data = static_cast<UVec4*>(
2320                         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 64 * sizeof(UVec4) * 5, 64 * sizeof(UVec4), GL_MAP_READ_BIT));
2321                 for (int i = 0; i < 8 * 8; ++i)
2322                         if (data[i].x() != 1000)
2323                                 error = ERROR;
2324                 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2325                 if (!CheckFinalCounterValue(counter_buffer_, 5 * sizeof(GLuint), 1000))
2326                         error = ERROR;
2327
2328                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_ssbo);
2329                 data = static_cast<UVec4*>(
2330                         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 64 * sizeof(UVec4) * 6, 64 * sizeof(UVec4), GL_MAP_READ_BIT));
2331                 if (!CheckCounterValues(8 * 8, data, 1000))
2332                         error = ERROR;
2333                 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2334                 if (!CheckFinalCounterValue(counter_buffer_, 6 * sizeof(GLuint), 1064))
2335                         error = ERROR;
2336
2337                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_ssbo);
2338                 data = static_cast<UVec4*>(
2339                         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 64 * sizeof(UVec4) * 7, 64 * sizeof(UVec4), GL_MAP_READ_BIT));
2340                 if (!CheckCounterValues(8 * 8, data, 1000))
2341                         error = ERROR;
2342                 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2343                 if (!CheckFinalCounterValue(counter_buffer_, 7 * sizeof(GLuint), 1064))
2344                         error = ERROR;
2345
2346                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
2347                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
2348                 return error;
2349         }
2350
2351         virtual long Cleanup()
2352         {
2353                 glDeleteBuffers(1, &counter_buffer_);
2354                 glDeleteBuffers(1, &m_ssbo);
2355                 glDeleteProgram(prog_);
2356                 glUseProgram(0);
2357                 return NO_ERROR;
2358         }
2359 };
2360
2361 class AdvancedUsageSwitchPrograms : public SACSubcaseBase
2362 {
2363         virtual std::string Title()
2364         {
2365                 return NL "Switching several program objects with different atomic counters with different bindings";
2366         }
2367         virtual std::string Purpose()
2368         {
2369                 return NL "Verify that each program upadate atomic counter buffer object in appropriate binding point.";
2370         }
2371         virtual std::string Method()
2372         {
2373                 return NL "";
2374         }
2375         virtual std::string PassCriteria()
2376         {
2377                 return NL "";
2378         }
2379
2380         GLuint counter_buffer_[8];
2381         GLuint xfb_buffer_;
2382         GLuint vao_, vbo_;
2383         GLuint prog_[8];
2384         GLuint fbo_, rt_;
2385
2386         std::string GenVSSrc(int binding, int offset)
2387         {
2388                 std::ostringstream os;
2389                 os << "#version 310 es" NL "layout(location = 0) in vec4 i_vertex;" NL "flat out uvec4 o_atomic_value;" NL
2390                           "layout(binding = "
2391                    << binding << ", offset = " << offset
2392                    << ") uniform atomic_uint ac_counter_vs;" NL "void main() {" NL "  gl_Position = i_vertex;" NL
2393                           "  o_atomic_value = uvec4(atomicCounterIncrement(ac_counter_vs));" NL "}";
2394                 return os.str();
2395         }
2396         std::string GenFSSrc(int binding, int offset)
2397         {
2398                 std::ostringstream os;
2399                 os << "#version 310 es" NL "layout(location = 0) out uvec4 o_color;" NL "layout(binding = " << binding
2400                    << ", offset = " << offset << ") uniform atomic_uint ac_counter_fs;" NL "void main() {" NL
2401                                                                                  "  o_color = uvec4(atomicCounterIncrement(ac_counter_fs));" NL "}";
2402                 return os.str();
2403         }
2404         virtual long Setup()
2405         {
2406                 memset(counter_buffer_, 0, sizeof(counter_buffer_));
2407                 xfb_buffer_ = 0;
2408                 vao_ = vbo_ = 0;
2409                 memset(prog_, 0, sizeof(prog_));
2410                 fbo_ = rt_ = 0;
2411                 return NO_ERROR;
2412         }
2413         virtual long Run()
2414         {
2415
2416                 GLint p1, p2, p3, p4;
2417                 glGetIntegerv(GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS, &p1);
2418                 glGetIntegerv(GL_MAX_VERTEX_ATOMIC_COUNTERS, &p2);
2419                 glGetIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS, &p3);
2420                 glGetIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTERS, &p4);
2421                 if (p1 < 8 || p2 < 1 || p3 < 8 || p4 < 1)
2422                 {
2423                         OutputNotSupported("GL_MAX_*_ATOMIC_COUNTER_BUFFERS or GL_MAX_*_ATOMIC_COUNTERS are less than required");
2424                         return NOT_SUPPORTED;
2425                 }
2426
2427                 // create programs
2428                 for (int i = 0; i < 8; ++i)
2429                 {
2430                         std::string vs_str  = GenVSSrc(i, i * 8);
2431                         std::string fs_str  = GenFSSrc(7 - i, 128 + i * 16);
2432                         const char* src_vs  = vs_str.c_str();
2433                         const char* src_fs  = fs_str.c_str();
2434                         prog_[i]                        = CreateProgram(src_vs, src_fs, false);
2435                         const char* xfb_var = "o_atomic_value";
2436                         glTransformFeedbackVaryings(prog_[i], 1, &xfb_var, GL_SEPARATE_ATTRIBS);
2437                         LinkProgram(prog_[i]);
2438                 }
2439
2440                 // create atomic counter buffers
2441                 glGenBuffers(8, counter_buffer_);
2442                 for (int i = 0; i < 8; ++i)
2443                 {
2444                         std::vector<GLuint> init_data(256);
2445                         glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, counter_buffer_[i]);
2446                         glBufferData(GL_ATOMIC_COUNTER_BUFFER, (GLsizeiptr)(init_data.size() * sizeof(GLuint)), &init_data[0],
2447                                                  GL_DYNAMIC_COPY);
2448                 }
2449                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
2450
2451                 // create transform feedback buffer
2452                 glGenBuffers(1, &xfb_buffer_);
2453                 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_buffer_);
2454                 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 1000, NULL, GL_STREAM_COPY);
2455                 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
2456
2457                 // create render target
2458                 const int s = 8;
2459                 glGenTextures(1, &rt_);
2460                 glBindTexture(GL_TEXTURE_2D, rt_);
2461                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2462                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2463                 glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, s, s, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, NULL);
2464                 glBindTexture(GL_TEXTURE_2D, 0);
2465
2466                 // create fbo
2467                 glGenFramebuffers(1, &fbo_);
2468                 glBindFramebuffer(GL_FRAMEBUFFER, fbo_);
2469                 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt_, 0);
2470                 glBindFramebuffer(GL_FRAMEBUFFER, 0);
2471
2472                 // create geometry
2473                 CreateTriangle(&vao_, &vbo_, NULL);
2474
2475                 // draw
2476                 for (GLuint i = 0; i < 8; ++i)
2477                 {
2478                         glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, i, counter_buffer_[i]);
2479                 }
2480                 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, xfb_buffer_);
2481                 glBindFramebuffer(GL_FRAMEBUFFER, fbo_);
2482                 glViewport(0, 0, s, s);
2483                 glBindVertexArray(vao_);
2484
2485                 for (int i = 0; i < 8; ++i)
2486                 {
2487                         glUseProgram(prog_[i]);
2488                         glBeginTransformFeedback(GL_TRIANGLES);
2489                         glDrawArrays(GL_TRIANGLES, 0, 3);
2490                         glEndTransformFeedback();
2491                         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2492
2493                         if (!CheckFinalCounterValue(counter_buffer_[i], i * 8, 3))
2494                                 return ERROR;
2495                         if (!CheckFinalCounterValue(counter_buffer_[7 - i], 128 + i * 16, 64))
2496                                 return ERROR;
2497                 }
2498                 return NO_ERROR;
2499         }
2500         virtual long Cleanup()
2501         {
2502                 glDeleteFramebuffers(1, &fbo_);
2503                 glDeleteTextures(1, &rt_);
2504                 glViewport(0, 0, getWindowWidth(), getWindowHeight());
2505                 glDeleteBuffers(8, counter_buffer_);
2506                 glDeleteBuffers(1, &xfb_buffer_);
2507                 glDeleteVertexArrays(1, &vao_);
2508                 glDeleteBuffers(1, &vbo_);
2509                 for (int i = 0; i < 8; ++i)
2510                         glDeleteProgram(prog_[i]);
2511                 glUseProgram(0);
2512                 return NO_ERROR;
2513         }
2514 };
2515
2516 class AdvancedUsageUBO : public BasicUsageCS
2517 {
2518         virtual std::string Title()
2519         {
2520                 return NL "Atomic Counters used to access Uniform Buffer Objects";
2521         }
2522         virtual std::string Purpose()
2523         {
2524                 return NL "Atomic counters are used to access UBOs. In that way each shader invocation can access UBO at "
2525                                   "unique offset." NL
2526                                   "This scenario is a base for some practical algorithms. Verify that it works as expected.";
2527         }
2528         virtual std::string Method()
2529         {
2530                 return NL "";
2531         }
2532         virtual std::string PassCriteria()
2533         {
2534                 return NL "";
2535         }
2536
2537         GLuint counter_buffer_, m_ssbo;
2538         GLuint uniform_buffer_;
2539         GLuint prog_;
2540
2541         virtual long Setup()
2542         {
2543                 counter_buffer_ = 0;
2544                 uniform_buffer_ = 0;
2545                 m_ssbo                  = 0;
2546                 prog_                   = 0;
2547                 return NO_ERROR;
2548         }
2549
2550         virtual long Run()
2551         {
2552                 // create program
2553                 const char* glsl_cs =
2554                         NL "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;" NL "layout(std430) buffer Output {" NL
2555                            "  mediump uvec4 color[256];" NL "} g_out;" NL
2556                            "layout(binding = 0, offset = 0) uniform atomic_uint ac_counter;" NL "layout(std140) uniform Data {" NL
2557                            "  mediump uint index[256];" NL "} ub_data;" NL "void main() {" NL
2558                            "  mediump uint offset = 16u * gl_GlobalInvocationID.y + gl_GlobalInvocationID.x;" NL
2559                            "  g_out.color[offset] = uvec4(ub_data.index[atomicCounterIncrement(ac_counter)]);" NL "}";
2560                 prog_ = CreateComputeProgram(glsl_cs);
2561                 glLinkProgram(prog_);
2562                 if (!CheckProgram(prog_))
2563                         return ERROR;
2564                 glUniformBlockBinding(prog_, glGetUniformBlockIndex(prog_, "Data"), 1);
2565
2566                 // create atomic counter buffer
2567                 const unsigned int z = 0;
2568                 glGenBuffers(1, &counter_buffer_);
2569                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, counter_buffer_);
2570                 glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(z), &z, GL_DYNAMIC_COPY);
2571                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
2572
2573                 // create uniform buffer
2574                 std::vector<UVec4> init_data(256);
2575                 for (GLuint i   = 0; i < 256; ++i)
2576                         init_data[i] = UVec4(i);
2577                 glGenBuffers(1, &uniform_buffer_);
2578                 glBindBuffer(GL_UNIFORM_BUFFER, uniform_buffer_);
2579                 glBufferData(GL_UNIFORM_BUFFER, (GLsizeiptr)(sizeof(UVec4) * init_data.size()), &init_data[0], GL_DYNAMIC_COPY);
2580                 glBindBuffer(GL_UNIFORM_BUFFER, 0);
2581
2582                 glGenBuffers(1, &m_ssbo);
2583                 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_ssbo);
2584                 glBufferData(GL_SHADER_STORAGE_BUFFER, 256 * sizeof(UVec4), NULL, GL_DYNAMIC_DRAW);
2585                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
2586
2587                 // draw
2588                 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, counter_buffer_);
2589                 glBindBufferBase(GL_UNIFORM_BUFFER, 1, uniform_buffer_);
2590                 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_ssbo);
2591                 glUseProgram(prog_);
2592                 glDispatchCompute(16, 16, 1);
2593
2594                 // validate
2595                 UVec4* data;
2596                 long   error = NO_ERROR;
2597                 glMemoryBarrier(GL_UNIFORM_BARRIER_BIT | GL_SHADER_STORAGE_BARRIER_BIT | GL_ATOMIC_COUNTER_BARRIER_BIT);
2598
2599                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_ssbo);
2600                 data = static_cast<UVec4*>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 256 * sizeof(UVec4), GL_MAP_READ_BIT));
2601                 if (!CheckCounterValues(16 * 16, data, 0))
2602                         error = ERROR;
2603                 if (!CheckFinalCounterValue(counter_buffer_, 0, 256))
2604                         error = ERROR;
2605                 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2606
2607                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
2608                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
2609
2610                 return error;
2611         }
2612
2613         virtual long Cleanup()
2614         {
2615                 glDeleteBuffers(1, &counter_buffer_);
2616                 glDeleteBuffers(1, &uniform_buffer_);
2617                 glDeleteBuffers(1, &m_ssbo);
2618                 glDeleteProgram(prog_);
2619                 glUseProgram(0);
2620                 return NO_ERROR;
2621         }
2622 };
2623
2624 class NegativeAPI : public SACSubcaseBase
2625 {
2626         virtual std::string Title()
2627         {
2628                 return NL "NegativeAPI";
2629         }
2630         virtual std::string Purpose()
2631         {
2632                 return NL "Verify errors reported by BindBuffer* commands.";
2633         }
2634         virtual std::string Method()
2635         {
2636                 return NL "";
2637         }
2638         virtual std::string PassCriteria()
2639         {
2640                 return NL "";
2641         }
2642
2643         GLuint buffer;
2644
2645         virtual long Setup()
2646         {
2647                 return NO_ERROR;
2648         }
2649         virtual long Run()
2650         {
2651                 long  error = NO_ERROR;
2652                 GLint res;
2653                 glGetIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, &res);
2654                 glGenBuffers(1, &buffer);
2655                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, buffer);
2656                 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, res, buffer);
2657                 if (glGetError() != GL_INVALID_VALUE)
2658                 {
2659                         Output("glBindBufferBase should generate INVALID_VALUE when"
2660                                    " index is greater than or equal GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS.\n");
2661                         error = ERROR;
2662                 }
2663                 glBindBufferRange(GL_ATOMIC_COUNTER_BUFFER, res, buffer, 0, 4);
2664                 if (glGetError() != GL_INVALID_VALUE)
2665                 {
2666                         Output("glBindBufferRange should generate INVALID_VALUE when"
2667                                    " index is greater than or equal GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS.\n");
2668                         error = ERROR;
2669                 }
2670                 glBindBufferRange(GL_ATOMIC_COUNTER_BUFFER, res - 1, buffer, 3, 4);
2671                 if (glGetError() != GL_INVALID_VALUE)
2672                 {
2673                         Output("glBindBufferRange should generate INVALID_VALUE when"
2674                                    " <offset> is not a multiple of four\n");
2675                         error = ERROR;
2676                 }
2677                 return error;
2678         }
2679         virtual long Cleanup()
2680         {
2681                 glDeleteBuffers(1, &buffer);
2682                 return NO_ERROR;
2683         }
2684 };
2685
2686 class NegativeGLSL : public BasicUsageCS
2687 {
2688         virtual std::string Title()
2689         {
2690                 return NL "GLSL errors";
2691         }
2692         virtual std::string Purpose()
2693         {
2694                 return NL "Verify that two different atomic counter uniforms with same binding cannot share same offset value.";
2695         }
2696         virtual std::string Method()
2697         {
2698                 return NL "";
2699         }
2700         virtual std::string PassCriteria()
2701         {
2702                 return NL "";
2703         }
2704
2705         GLuint prog_;
2706
2707         virtual long Setup()
2708         {
2709                 prog_ = 0;
2710                 return NO_ERROR;
2711         }
2712
2713         virtual long Run()
2714         {
2715                 const char* const glsl_cs = NL
2716                         "layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;" NL
2717                         "layout(binding = 0, offset = 4) uniform atomic_uint ac_counter_inc;" NL
2718                         "layout(binding = 0, offset = 4) uniform atomic_uint ac_counter_dec;" NL "layout(std430) buffer Output {" NL
2719                         "  mediump uint data_inc[256];" NL "  mediump uint data_dec[256];" NL "} g_out;" NL "void main() {" NL
2720                         "  mediump uint offset = 32u * gl_GlobalInvocationID.y + gl_GlobalInvocationID.x;" NL
2721                         "  g_out.data_inc[offset] = atomicCounterIncrement(ac_counter_inc);" NL
2722                         "  g_out.data_dec[offset] = atomicCounterDecrement(ac_counter_dec);" NL "}";
2723
2724                 prog_ = CreateComputeProgram(glsl_cs);
2725                 glLinkProgram(prog_);
2726                 if (CheckProgram(prog_))
2727                 {
2728                         Output("Link should fail because ac_counter0 and ac_counter2 uses same binding and same offset.\n");
2729                         return ERROR;
2730                 }
2731                 return NO_ERROR;
2732         }
2733         virtual long Cleanup()
2734         {
2735                 glDeleteProgram(prog_);
2736                 return NO_ERROR;
2737         }
2738 };
2739
2740 class AdvancedManyDrawCalls : public SACSubcaseBase
2741 {
2742         virtual std::string Title()
2743         {
2744                 return NL "Atomic Counters usage in multiple draw calls";
2745         }
2746         virtual std::string Purpose()
2747         {
2748                 return NL "Verify atomic counters behaviour across multiple draw calls.";
2749         }
2750         virtual std::string Method()
2751         {
2752                 return NL "";
2753         }
2754         virtual std::string PassCriteria()
2755         {
2756                 return NL "";
2757         }
2758
2759         GLuint counter_buffer_;
2760         GLuint vao_, vbo_;
2761         GLuint prog_;
2762         GLuint fbo_, rt_[2];
2763
2764         virtual long Setup()
2765         {
2766                 counter_buffer_ = 0;
2767                 vao_ = vbo_ = 0;
2768                 prog_           = 0;
2769                 fbo_ = rt_[0] = rt_[1] = 0;
2770                 return NO_ERROR;
2771         }
2772         virtual long Run()
2773         {
2774
2775                 GLint p1, p2;
2776                 glGetIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS, &p1);
2777                 glGetIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTERS, &p2);
2778                 if (p1 < 1 || p2 < 2)
2779                 {
2780                         OutputNotSupported(
2781                                 "GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS or GL_MAX_FRAGMENT_ATOMIC_COUNTERS are less than required");
2782                         return NOT_SUPPORTED;
2783                 }
2784
2785                 // create program
2786                 const char* src_vs = "#version 310 es" NL "layout(location = 0) in vec4 i_vertex;" NL "void main() {" NL
2787                                                          "  gl_Position = i_vertex;" NL "}";
2788                 const char* src_fs = "#version 310 es" NL "layout(location = 0) out uvec4 o_color[2];" NL
2789                                                          "layout(binding = 0, offset = 0) uniform atomic_uint ac_counter_inc;" NL
2790                                                          "layout(binding = 0, offset = 4) uniform atomic_uint ac_counter_dec;" NL "void main() {" NL
2791                                                          "  o_color[0] = uvec4(atomicCounterIncrement(ac_counter_inc));" NL
2792                                                          "  o_color[1] = uvec4(atomicCounterDecrement(ac_counter_dec));" NL "}";
2793                 prog_ = CreateProgram(src_vs, src_fs, true);
2794
2795                 // create atomic counter buffer
2796                 glGenBuffers(1, &counter_buffer_);
2797                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, counter_buffer_);
2798                 glBufferData(GL_ATOMIC_COUNTER_BUFFER, 8, NULL, GL_DYNAMIC_COPY);
2799                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
2800
2801                 // create render targets
2802                 const int s = 8;
2803                 glGenTextures(2, rt_);
2804
2805                 for (int i = 0; i < 2; ++i)
2806                 {
2807                         glBindTexture(GL_TEXTURE_2D, rt_[i]);
2808                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2809                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2810                         glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, s, s, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, NULL);
2811                         glBindTexture(GL_TEXTURE_2D, 0);
2812                 }
2813
2814                 // create fbo
2815                 glGenFramebuffers(1, &fbo_);
2816                 glBindFramebuffer(GL_FRAMEBUFFER, fbo_);
2817                 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt_[0], 0);
2818                 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, rt_[1], 0);
2819                 const GLenum draw_buffers[2] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
2820                 glDrawBuffers(2, draw_buffers);
2821                 glBindFramebuffer(GL_FRAMEBUFFER, 0);
2822
2823                 // create geometry
2824                 CreateQuad(&vao_, &vbo_, NULL);
2825
2826                 // init counter buffer
2827                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, counter_buffer_);
2828                 unsigned int* ptr = static_cast<unsigned int*>(
2829                         glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, 8, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT));
2830                 *ptr++ = 0;
2831                 *ptr++ = 256;
2832                 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
2833
2834                 // draw
2835                 glBindFramebuffer(GL_FRAMEBUFFER, fbo_);
2836                 glViewport(0, 0, s, s);
2837                 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, counter_buffer_);
2838                 glUseProgram(prog_);
2839                 glBindVertexArray(vao_);
2840
2841                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2842                 glMemoryBarrier(GL_ATOMIC_COUNTER_BARRIER_BIT);
2843                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2844                 glMemoryBarrier(GL_ATOMIC_COUNTER_BARRIER_BIT);
2845                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2846                 glMemoryBarrier(GL_ATOMIC_COUNTER_BARRIER_BIT);
2847                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2848
2849                 // validate
2850                 UVec4 data[s * s];
2851                 glReadBuffer(GL_COLOR_ATTACHMENT0);
2852                 glReadPixels(0, 0, s, s, GL_RGBA_INTEGER, GL_UNSIGNED_INT, data);
2853                 if (!CheckCounterValues(s * s, data, s * s * 3))
2854                         return ERROR;
2855
2856                 glReadBuffer(GL_COLOR_ATTACHMENT1);
2857                 glReadPixels(0, 0, s, s, GL_RGBA_INTEGER, GL_UNSIGNED_INT, data);
2858                 if (!CheckCounterValues(s * s, data, 0))
2859                         return ERROR;
2860
2861                 if (!CheckFinalCounterValue(counter_buffer_, 0, 256))
2862                         return ERROR;
2863                 if (!CheckFinalCounterValue(counter_buffer_, 4, 0))
2864                         return ERROR;
2865
2866                 return NO_ERROR;
2867         }
2868
2869         virtual long Cleanup()
2870         {
2871                 glDeleteFramebuffers(1, &fbo_);
2872                 glDeleteTextures(2, rt_);
2873                 glViewport(0, 0, getWindowWidth(), getWindowHeight());
2874                 glDeleteBuffers(1, &counter_buffer_);
2875                 glDeleteVertexArrays(1, &vao_);
2876                 glDeleteBuffers(1, &vbo_);
2877                 glDeleteProgram(prog_);
2878                 glUseProgram(0);
2879                 return NO_ERROR;
2880         }
2881 };
2882
2883 class NegativeSSBO : public BasicUsageCS
2884 {
2885         virtual std::string Title()
2886         {
2887                 return NL "GLSL errors";
2888         }
2889         virtual std::string Purpose()
2890         {
2891                 return NL "Verify that atomic counters cannot be declared in the buffer block.";
2892         }
2893         virtual std::string Method()
2894         {
2895                 return NL "";
2896         }
2897         virtual std::string PassCriteria()
2898         {
2899                 return NL "";
2900         }
2901
2902         GLuint prog_;
2903
2904         virtual long Setup()
2905         {
2906                 prog_ = 0;
2907                 return NO_ERROR;
2908         }
2909         virtual long Run()
2910         {
2911
2912                 const char* const glsl_cs =
2913                         NL "layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;" NL
2914                            "layout(binding = 0, offset = 0) uniform atomic_uint ac_counter_dec;" NL
2915                            "layout(std430) buffer Output {" NL "  mediump uint data_inc[256];" NL "  mediump uint data_dec[256];" NL
2916                            "  layout(binding = 0, offset = 16) uniform atomic_uint ac_counter0;" NL "} g_out;" NL "void main() {" NL
2917                            "  mediump uint offset = 32u * gl_GlobalInvocationID.y + gl_GlobalInvocationID.x;" NL
2918                            "  g_out.data_inc[offset] = atomicCounterIncrement(ac_counter0);" NL
2919                            "  g_out.data_dec[offset] = atomicCounterDecrement(ac_counter_dec);" NL "}";
2920
2921                 prog_ = CreateComputeProgram(glsl_cs);
2922                 glLinkProgram(prog_);
2923                 if (CheckProgram(prog_))
2924                 {
2925                         Output("Link should fail because atomic counters cannot be declared in the buffer block.\n");
2926                         return ERROR;
2927                 }
2928                 return NO_ERROR;
2929         }
2930         virtual long Cleanup()
2931         {
2932                 glDeleteProgram(prog_);
2933                 return NO_ERROR;
2934         }
2935 };
2936
2937 class NegativeUBO : public BasicUsageCS
2938 {
2939         virtual std::string Title()
2940         {
2941                 return NL "GLSL errors";
2942         }
2943         virtual std::string Purpose()
2944         {
2945                 return NL "Verify that atomic counters cannot be declared in uniform block.";
2946         }
2947         virtual std::string Method()
2948         {
2949                 return NL "";
2950         }
2951         virtual std::string PassCriteria()
2952         {
2953                 return NL "";
2954         }
2955
2956         GLuint prog_;
2957
2958         virtual long Setup()
2959         {
2960                 prog_ = 0;
2961                 return NO_ERROR;
2962         }
2963
2964         virtual long Run()
2965         {
2966                 const char* const glsl_cs =
2967                         NL "layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;" NL "uniform Block {" NL
2968                            "  uniform atomic_uint ac_counter;" NL "};" NL "layout(std430) buffer Output {" NL
2969                            "  mediump uint data_inc[256];" NL "} g_out;" NL "void main() {" NL
2970                            "  mediump uint offset = 32u * gl_GlobalInvocationID.y + gl_GlobalInvocationID.x;" NL
2971                            "  g_out.data_inc[offset] = atomicCounterIncrement(ac_counter);" NL "}";
2972
2973                 prog_ = CreateComputeProgram(glsl_cs);
2974                 glLinkProgram(prog_);
2975                 if (CheckProgram(prog_))
2976                 {
2977                         Output("Link should fail because atomic counters cannot be declared in the uniform block.\n");
2978                         return ERROR;
2979                 }
2980                 return NO_ERROR;
2981         }
2982
2983         virtual long Cleanup()
2984         {
2985                 glDeleteProgram(prog_);
2986                 return NO_ERROR;
2987         }
2988 };
2989
2990 class BasicUsageNoOffset : public BasicUsageCS
2991 {
2992         virtual std::string Title()
2993         {
2994                 return NL "Atomic Counters usage in the Compute Shader stage";
2995         }
2996         virtual std::string Purpose()
2997         {
2998                 return NL "Verify that atomic counters work as expected in the Compute Shader stage when decalred with no "
2999                                   "offset qualifier." NL "In particular make sure that values returned by GLSL built-in functions" NL
3000                                   "atomicCounterIncrement and atomicCounterDecrement are unique in every shader invocation." NL
3001                                   "Also make sure that the final values in atomic counter buffer objects are as expected.";
3002         }
3003         virtual std::string Method()
3004         {
3005                 return NL "";
3006         }
3007         virtual std::string PassCriteria()
3008         {
3009                 return NL "";
3010         }
3011
3012         GLuint counter_buffer_;
3013         GLuint prog_;
3014         GLuint m_buffer;
3015
3016         virtual long Setup()
3017         {
3018                 counter_buffer_ = 0;
3019                 prog_                   = 0;
3020                 m_buffer                = 0;
3021                 return NO_ERROR;
3022         }
3023
3024         virtual long Run()
3025         {
3026                 // create program
3027                 const char* const glsl_cs =
3028                         NL "layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;" NL
3029                            "layout(binding = 0) uniform atomic_uint ac_counter_inc;" NL
3030                            "layout(binding = 0) uniform atomic_uint ac_counter_dec;" NL "layout(std430) buffer Output {" NL
3031                            "  mediump uint data_inc[256];" NL "  mediump uint data_dec[256];" NL "} g_out;" NL "void main() {" NL
3032                            "  mediump uint offset = 32u * gl_GlobalInvocationID.y + gl_GlobalInvocationID.x;" NL
3033                            "  g_out.data_inc[offset] = atomicCounterIncrement(ac_counter_inc);" NL
3034                            "  g_out.data_dec[offset] = atomicCounterDecrement(ac_counter_dec);" NL "}";
3035                 prog_ = CreateComputeProgram(glsl_cs);
3036                 glLinkProgram(prog_);
3037                 if (!CheckProgram(prog_))
3038                         return ERROR;
3039
3040                 // create atomic counter buffer
3041                 glGenBuffers(1, &counter_buffer_);
3042                 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, counter_buffer_);
3043                 glBufferData(GL_ATOMIC_COUNTER_BUFFER, 8, NULL, GL_DYNAMIC_COPY);
3044                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
3045
3046                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, counter_buffer_);
3047                 unsigned int* ptr = static_cast<unsigned int*>(
3048                         glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, 8, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT));
3049                 *ptr++ = 0;
3050                 *ptr++ = 256;
3051                 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
3052
3053                 glGenBuffers(1, &m_buffer);
3054                 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
3055                 glBufferData(GL_SHADER_STORAGE_BUFFER, 512 * sizeof(GLuint), NULL, GL_DYNAMIC_DRAW);
3056                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
3057
3058                 glUseProgram(prog_);
3059                 glDispatchCompute(4, 1, 1);
3060
3061                 long    error = NO_ERROR;
3062                 GLuint* data;
3063                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer);
3064                 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3065                 data = static_cast<GLuint*>(
3066                         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 512 * sizeof(GLuint), GL_MAP_READ_BIT | GL_MAP_WRITE_BIT));
3067
3068                 std::sort(data, data + 512);
3069                 for (int i = 0; i < 512; i += 2)
3070                 {
3071                         if (data[i] != data[i + 1])
3072                         {
3073                                 Output("Pair of values should be equal, got: %d, %d\n", data[i], data[i + 1]);
3074                                 error = ERROR;
3075                         }
3076                         if (i < 510 && data[i] == data[i + 2])
3077                         {
3078                                 Output("Too many same values found: %d, index: %d\n", data[i], i);
3079                                 error = ERROR;
3080                         }
3081                 }
3082
3083                 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3084                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
3085                 return error;
3086         }
3087
3088         virtual long Cleanup()
3089         {
3090                 glDeleteBuffers(1, &counter_buffer_);
3091                 glDeleteBuffers(1, &m_buffer);
3092                 glDeleteProgram(prog_);
3093                 glUseProgram(0);
3094                 return NO_ERROR;
3095         }
3096 };
3097
3098 class NegativeUniform : public SACSubcaseBase
3099 {
3100         virtual std::string Title()
3101         {
3102                 return NL "GLSL errors";
3103         }
3104         virtual std::string Purpose()
3105         {
3106                 return NL "Verify that atomicCounterIncrement/atomicCounterDecrement "
3107                                   "cannot be used on normal uniform.";
3108         }
3109         virtual std::string Method()
3110         {
3111                 return NL "";
3112         }
3113         virtual std::string PassCriteria()
3114         {
3115                 return NL "";
3116         }
3117
3118         GLuint prog_;
3119
3120         virtual long Setup()
3121         {
3122                 prog_ = 0;
3123                 return NO_ERROR;
3124         }
3125         virtual long Run()
3126         {
3127
3128                 GLint p1, p2;
3129                 glGetIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS, &p1);
3130                 glGetIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTERS, &p2);
3131                 if (p1 < 1 || p2 < 1)
3132                 {
3133                         OutputNotSupported(
3134                                 "GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS or GL_MAX_FRAGMENT_ATOMIC_COUNTERS are less than required");
3135                         return NOT_SUPPORTED;
3136                 }
3137
3138                 // create program
3139                 const char* glsl_vs = "#version 310 es" NL "layout(location = 0) in vec4 i_vertex;" NL "void main() {" NL
3140                                                           "  gl_Position = i_vertex;" NL "}";
3141
3142                 const char* glsl_fs1 =
3143                         "#version 310 es" NL "layout(location = 0) out uvec4 o_color[4];" NL "uniform uint ac_counter0;" NL
3144                         "void main() {" NL "  o_color[0] = uvec4(atomicCounterIncrement(ac_counter0));" NL "}";
3145
3146                 prog_ = glCreateProgram();
3147
3148                 GLuint sh = glCreateShader(GL_VERTEX_SHADER);
3149                 glAttachShader(prog_, sh);
3150                 glShaderSource(sh, 1, &glsl_vs, NULL);
3151                 glCompileShader(sh);
3152                 GLint status_comp;
3153                 glGetShaderiv(sh, GL_COMPILE_STATUS, &status_comp);
3154                 if (status_comp != GL_TRUE)
3155                 {
3156                         Output("Unexpected error during vertex shader compilation.");
3157                         return ERROR;
3158                 }
3159                 glDeleteShader(sh);
3160
3161                 sh = glCreateShader(GL_FRAGMENT_SHADER);
3162                 glAttachShader(prog_, sh);
3163                 glShaderSource(sh, 1, &glsl_fs1, NULL);
3164                 glCompileShader(sh);
3165                 glGetShaderiv(sh, GL_COMPILE_STATUS, &status_comp);
3166                 glDeleteShader(sh);
3167
3168                 GLint status;
3169                 glLinkProgram(prog_);
3170                 glGetProgramiv(prog_, GL_LINK_STATUS, &status);
3171                 if (status_comp == GL_TRUE && status == GL_TRUE)
3172                 {
3173                         Output("Expected error during fragment shader compilation or linking.");
3174                         return ERROR;
3175                 }
3176                 return NO_ERROR;
3177         }
3178         virtual long Cleanup()
3179         {
3180                 glDeleteProgram(prog_);
3181                 return NO_ERROR;
3182         }
3183 };
3184
3185 class NegativeArray : public BasicUsageCS
3186 {
3187         virtual std::string Title()
3188         {
3189                 return NL "GLSL errors";
3190         }
3191         virtual std::string Purpose()
3192         {
3193                 return NL "Verify that atomicCounterIncrement/atomicCounterDecrement "
3194                                   "cannot be used on array of atomic counters.";
3195         }
3196         virtual std::string Method()
3197         {
3198                 return NL "";
3199         }
3200         virtual std::string PassCriteria()
3201         {
3202                 return NL "";
3203         }
3204
3205         GLuint prog_;
3206
3207         virtual long Setup()
3208         {
3209                 prog_ = 0;
3210                 return NO_ERROR;
3211         }
3212         virtual long Run()
3213         {
3214
3215                 const char* const glsl_cs =
3216                         NL "layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;" NL
3217                            "layout(binding = 0) uniform atomic_uint ac_counter[3];" NL "layout(std430) buffer Output {" NL
3218                            "  mediump uint data_inc[256];" NL "} g_out;" NL "void main() {" NL
3219                            "  mediump uint offset = 32u * gl_GlobalInvocationID.y + gl_GlobalInvocationID.x;" NL
3220                            "  g_out.data_inc[offset] = atomicCounterIncrement(ac_counter);" NL "}";
3221
3222                 prog_ = CreateComputeProgram(glsl_cs);
3223                 glLinkProgram(prog_);
3224                 if (CheckProgram(prog_))
3225                 {
3226                         Output("Link should fail because atomicCounterIncrement cannot be used on array of atomic counters.\n");
3227                         return ERROR;
3228                 }
3229                 return NO_ERROR;
3230         }
3231         virtual long Cleanup()
3232         {
3233                 glDeleteProgram(prog_);
3234                 return NO_ERROR;
3235         }
3236 };
3237
3238 class NegativeArithmetic : public BasicUsageCS
3239 {
3240         virtual std::string Title()
3241         {
3242                 return NL "GLSL errors";
3243         }
3244         virtual std::string Purpose()
3245         {
3246                 return NL "Verify that standard arithmetic operations \n"
3247                                   "cannot be performed on atomic counters.";
3248         }
3249         virtual std::string Method()
3250         {
3251                 return NL "";
3252         }
3253         virtual std::string PassCriteria()
3254         {
3255                 return NL "";
3256         }
3257
3258         GLuint prog_;
3259
3260         virtual long Setup()
3261         {
3262                 prog_ = 0;
3263                 return NO_ERROR;
3264         }
3265         virtual long Run()
3266         {
3267
3268                 const char* const glsl_cs =
3269                         NL "layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;" NL
3270                            "layout(binding = 0) uniform atomic_uint ac_counter;" NL "layout(std430) buffer Output {" NL
3271                            "  mediump uint data_inc[256];" NL "} g_out;" NL "void main() {" NL
3272                            "  mediump uint offset = 32u * gl_GlobalInvocationID.y + gl_GlobalInvocationID.x;" NL
3273                            "  g_out.data_inc[offset] = ac_counter + 1;" NL "}";
3274
3275                 prog_ = CreateComputeProgram(glsl_cs);
3276                 glLinkProgram(prog_);
3277                 if (CheckProgram(prog_))
3278                 {
3279                         Output(
3280                                 "Link should fail because atomic counters cannot be incremented by standard arithmetic operations.\n");
3281                         return ERROR;
3282                 }
3283                 return NO_ERROR;
3284         }
3285
3286         virtual long Cleanup()
3287         {
3288                 glDeleteProgram(prog_);
3289                 return NO_ERROR;
3290         }
3291 };
3292
3293 class AdvancedManyDrawCalls2 : public SACSubcaseBase
3294 {
3295
3296         GLuint m_acbo, m_ssbo;
3297         GLuint m_vao;
3298         GLuint m_ppo, m_vsp, m_fsp;
3299
3300         virtual long Setup()
3301         {
3302                 glGenBuffers(1, &m_acbo);
3303                 glGenBuffers(1, &m_ssbo);
3304                 glGenVertexArrays(1, &m_vao);
3305                 glGenProgramPipelines(1, &m_ppo);
3306                 m_vsp = m_fsp = 0;
3307                 return NO_ERROR;
3308         }
3309
3310         virtual long Cleanup()
3311         {
3312                 glDeleteBuffers(1, &m_acbo);
3313                 glDeleteBuffers(1, &m_ssbo);
3314                 glDeleteVertexArrays(1, &m_vao);
3315                 glDeleteProgramPipelines(1, &m_ppo);
3316                 glDeleteProgram(m_vsp);
3317                 glDeleteProgram(m_fsp);
3318                 return NO_ERROR;
3319         }
3320
3321         virtual long Run()
3322         {
3323
3324                 GLint p1, p2;
3325                 glGetIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS, &p1);
3326                 glGetIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTERS, &p2);
3327                 if (p1 < 1 || p2 < 1)
3328                 {
3329                         OutputNotSupported(
3330                                 "GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS or GL_MAX_FRAGMENT_ATOMIC_COUNTERS are less than required");
3331                         return NOT_SUPPORTED;
3332                 }
3333
3334                 const char* const glsl_vs = "#version 310 es" NL "void main() {" NL "#ifdef GL_ES" NL
3335                                                                         "  gl_PointSize = 1.0f;" NL "#endif" NL "  gl_Position = vec4(0, 0, 0, 1);" NL "}";
3336                 const char* const glsl_fs =
3337                         "#version 310 es" NL "layout(binding = 0) uniform atomic_uint g_counter;" NL
3338                         "layout(std430, binding = 0) buffer Output {" NL "  uint g_output[];" NL "};" NL "void main() {" NL
3339                         "  uint c = atomicCounterIncrement(g_counter);" NL "  g_output[c] = c;" NL "}";
3340
3341                 m_vsp = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &glsl_vs);
3342                 m_fsp = glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1, &glsl_fs);
3343                 if (!CheckProgram(m_vsp) || !CheckProgram(m_fsp))
3344                         return ERROR;
3345
3346                 glUseProgramStages(m_ppo, GL_VERTEX_SHADER_BIT, m_vsp);
3347                 glUseProgramStages(m_ppo, GL_FRAGMENT_SHADER_BIT, m_fsp);
3348
3349                 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, m_acbo);
3350                 {
3351                         GLuint data = 0;
3352                         glBufferData(GL_ATOMIC_COUNTER_BUFFER, 4, &data, GL_DYNAMIC_COPY);
3353                 }
3354
3355                 {
3356                         std::vector<GLuint> data(1000, 0xffff);
3357                         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_ssbo);
3358                         glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)(data.size() * 4), &data[0], GL_DYNAMIC_READ);
3359                 }
3360
3361                 // draw
3362                 glViewport(0, 0, 1, 1);
3363                 glBindProgramPipeline(m_ppo);
3364                 glBindVertexArray(m_vao);
3365                 for (int i = 0; i < 100; ++i)
3366                 {
3367                         glDrawArrays(GL_POINTS, 0, 1);
3368                 }
3369
3370                 glViewport(0, 0, getWindowWidth(), getWindowHeight());
3371
3372                 long status = NO_ERROR;
3373
3374                 {
3375                         GLuint* data;
3376
3377                         glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_acbo);
3378                         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3379                         data = static_cast<GLuint*>(glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, 4, GL_MAP_READ_BIT));
3380                         if (data[0] != 100)
3381                         {
3382                                 status = ERROR;
3383                                 Output("AC buffer content is %u, sholud be 100.\n", data[0]);
3384                         }
3385                         glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
3386                         glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
3387
3388                         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_ssbo);
3389                         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3390                         data = static_cast<GLuint*>(
3391                                 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 100 * 4, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT));
3392                         std::sort(data, data + 100);
3393                         for (GLuint i = 0; i < 100; ++i)
3394                         {
3395                                 if (data[i] != i)
3396                                 {
3397                                         status = ERROR;
3398                                         Output("data[%u] is %u, should be %u.\n", i, data[i], i);
3399                                 }
3400                         }
3401                         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3402                         glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
3403                 }
3404
3405                 return status;
3406         }
3407 };
3408
3409 class AdvancedUsageMultipleComputeDispatches : public SACSubcaseBase
3410 {
3411         GLuint m_acbo, m_ssbo;
3412         GLuint m_ppo, m_csp;
3413
3414         virtual long Setup()
3415         {
3416                 glGenBuffers(1, &m_acbo);
3417                 glGenBuffers(1, &m_ssbo);
3418                 glGenProgramPipelines(1, &m_ppo);
3419                 m_csp = 0;
3420                 return NO_ERROR;
3421         }
3422
3423         virtual long Cleanup()
3424         {
3425                 glDeleteBuffers(1, &m_acbo);
3426                 glDeleteBuffers(1, &m_ssbo);
3427                 glDeleteProgramPipelines(1, &m_ppo);
3428                 glDeleteProgram(m_csp);
3429                 return NO_ERROR;
3430         }
3431
3432         virtual long Run()
3433         {
3434                 // create program
3435                 const char* const glsl_cs =
3436                         "#version 310 es" NL "layout(local_size_x = 1) in;" NL
3437                         "layout(binding = 0) uniform atomic_uint g_counter;" NL "layout(std430, binding = 0) buffer Output {" NL
3438                         "  mediump uint g_output[];" NL "};" NL "void main() {" NL
3439                         "  mediump uint c = atomicCounterIncrement(g_counter);" NL "  g_output[c] = c;" NL "}";
3440
3441                 m_csp = glCreateShaderProgramv(GL_COMPUTE_SHADER, 1, &glsl_cs);
3442                 if (!CheckProgram(m_csp))
3443                         return ERROR;
3444                 glUseProgramStages(m_ppo, GL_COMPUTE_SHADER_BIT, m_csp);
3445
3446                 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, m_acbo);
3447                 {
3448                         GLuint data = 0;
3449                         glBufferData(GL_ATOMIC_COUNTER_BUFFER, 4, &data, GL_DYNAMIC_COPY);
3450                 }
3451
3452                 {
3453                         std::vector<GLuint> data(1000, 0xffff);
3454                         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_ssbo);
3455                         glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)(data.size() * 4), &data[0], GL_DYNAMIC_READ);
3456                 }
3457
3458                 glBindProgramPipeline(m_ppo);
3459                 for (int i = 0; i < 100; ++i)
3460                 {
3461                         glDispatchCompute(1, 1, 1);
3462                 }
3463
3464                 long status = NO_ERROR;
3465
3466                 {
3467                         GLuint* data;
3468
3469                         glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_acbo);
3470                         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3471                         data = static_cast<GLuint*>(glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, 4, GL_MAP_READ_BIT));
3472                         if (data[0] != 100)
3473                         {
3474                                 status = ERROR;
3475                                 Output("AC buffer content is %u, sholud be 100.\n", data[0]);
3476                         }
3477                         glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
3478                         glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
3479
3480                         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_ssbo);
3481                         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3482                         data = static_cast<GLuint*>(
3483                                 glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 100 * 4, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT));
3484                         std::sort(data, data + 100);
3485                         for (GLuint i = 0; i < 100; ++i)
3486                         {
3487                                 if (data[i] != i)
3488                                 {
3489                                         status = ERROR;
3490                                         Output("data[%u] is %u, should be %u.\n", i, data[i], i);
3491                                 }
3492                         }
3493                         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3494                         glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
3495                 }
3496
3497                 return status;
3498         }
3499 };
3500
3501 class BasicGLSLBuiltIn : public BasicUsageCS
3502 {
3503 public:
3504         virtual std::string Title()
3505         {
3506                 return NL "gl_Max* Check";
3507         }
3508         virtual std::string Purpose()
3509         {
3510                 return NL "Verify that gl_Max*Counters and gl_Max*Bindings exist in glsl and their values are no lower" NL
3511                                   "than minimum required by the spec and are no different from their GL_MAX_* counterparts.";
3512         }
3513
3514         GLuint prog_;
3515         GLuint m_buffer;
3516
3517         virtual long Setup()
3518         {
3519                 prog_   = 0;
3520                 m_buffer = 0;
3521                 return NO_ERROR;
3522         }
3523
3524         virtual long Run()
3525         {
3526                 // create program
3527                 const char* const glsl_cs = NL
3528                         "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;" NL "layout(std430) buffer Output {" NL
3529                         "  mediump uint data;" NL "} g_out;" NL "uniform mediump int m_vac;" NL "uniform mediump int m_fac;" NL
3530                         "uniform mediump int m_csac;" NL "uniform mediump int m_cac;" NL "uniform mediump int m_abuf;" NL
3531                         "void main() {" NL "  mediump uint res = 1u;" NL
3532                         "  if (gl_MaxVertexAtomicCounters < 0 || gl_MaxVertexAtomicCounters != m_vac)" NL "     res = res * 2u;" NL
3533                         "  if (gl_MaxFragmentAtomicCounters < 0 || gl_MaxFragmentAtomicCounters != m_fac)" NL
3534                         "     res = res * 3u;" NL
3535                         "  if (gl_MaxComputeAtomicCounters < 8 || gl_MaxComputeAtomicCounters != m_csac)" NL
3536                         "     res = res * 5u;" NL
3537                         "  if (gl_MaxCombinedAtomicCounters < 8 || gl_MaxCombinedAtomicCounters != m_cac)" NL
3538                         "     res = res * 7u;" NL
3539                         "  if (gl_MaxAtomicCounterBindings < 1 || gl_MaxAtomicCounterBindings != m_abuf)" NL
3540                         "     res = res * 11u;" NL "  g_out.data = res;" NL "}";
3541
3542                 prog_ = CreateComputeProgram(glsl_cs);
3543                 glLinkProgram(prog_);
3544                 if (!CheckProgram(prog_))
3545                         return ERROR;
3546                 glUseProgram(prog_);
3547
3548                 int m_vac;
3549                 int m_fac;
3550                 int m_csac;
3551                 int m_cac;
3552                 int m_abuf;
3553                 glGetIntegerv(GL_MAX_VERTEX_ATOMIC_COUNTERS, &m_vac);
3554                 glUniform1i(glGetUniformLocation(prog_, "m_vac"), m_vac);
3555                 glGetIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTERS, &m_fac);
3556                 glUniform1i(glGetUniformLocation(prog_, "m_fac"), m_fac);
3557                 glGetIntegerv(GL_MAX_COMPUTE_ATOMIC_COUNTERS, &m_csac);
3558                 glUniform1i(glGetUniformLocation(prog_, "m_csac"), m_csac);
3559                 glGetIntegerv(GL_MAX_COMBINED_ATOMIC_COUNTERS, &m_cac);
3560                 glUniform1i(glGetUniformLocation(prog_, "m_cac"), m_cac);
3561                 glGetIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, &m_abuf);
3562                 glUniform1i(glGetUniformLocation(prog_, "m_abuf"), m_abuf);
3563
3564                 glGenBuffers(1, &m_buffer);
3565                 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
3566                 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLuint), NULL, GL_DYNAMIC_DRAW);
3567                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
3568
3569                 glDispatchCompute(1, 1, 1);
3570
3571                 long    error = NO_ERROR;
3572                 GLuint* data;
3573                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer);
3574                 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3575                 data = static_cast<GLuint*>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(GLuint), GL_MAP_READ_BIT));
3576                 if (data[0] != 1u)
3577                 {
3578                         Output("Expected 1, got: %d", data[0]);
3579                         error = ERROR;
3580                 }
3581                 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3582                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
3583
3584                 return error;
3585         }
3586
3587         virtual long Cleanup()
3588         {
3589                 glDeleteBuffers(1, &m_buffer);
3590                 glDeleteProgram(prog_);
3591                 glUseProgram(0);
3592                 return NO_ERROR;
3593         }
3594 };
3595
3596 ShaderAtomicCountersTests::ShaderAtomicCountersTests(glcts::Context& context)
3597         : TestCaseGroup(context, "shader_atomic_counters", "")
3598 {
3599 }
3600
3601 ShaderAtomicCountersTests::~ShaderAtomicCountersTests(void)
3602 {
3603 }
3604
3605 void ShaderAtomicCountersTests::init()
3606 {
3607         using namespace glcts;
3608         setOutput(m_context.getTestContext().getLog());
3609         addChild(new TestSubcase(m_context, "basic-buffer-operations", TestSubcase::Create<BasicBufferOperations>));
3610         addChild(new TestSubcase(m_context, "basic-buffer-state", TestSubcase::Create<BasicBufferState>));
3611         addChild(new TestSubcase(m_context, "basic-buffer-bind", TestSubcase::Create<BasicBufferBind>));
3612         addChild(new TestSubcase(m_context, "basic-program-max", TestSubcase::Create<BasicProgramMax>));
3613         addChild(new TestSubcase(m_context, "basic-program-query", TestSubcase::Create<BasicProgramQuery>));
3614         addChild(new TestSubcase(m_context, "basic-usage-simple", TestSubcase::Create<BasicUsageSimple>));
3615         addChild(new TestSubcase(m_context, "basic-usage-no-offset", TestSubcase::Create<BasicUsageNoOffset>));
3616         addChild(new TestSubcase(m_context, "basic-usage-fs", TestSubcase::Create<BasicUsageFS>));
3617         addChild(new TestSubcase(m_context, "basic-usage-vs", TestSubcase::Create<BasicUsageVS>));
3618         addChild(new TestSubcase(m_context, "basic-usage-cs", TestSubcase::Create<BasicUsageCS>));
3619         addChild(new TestSubcase(m_context, "basic-glsl-built-in", TestSubcase::Create<BasicGLSLBuiltIn>));
3620         addChild(new TestSubcase(m_context, "advanced-usage-multi-stage", TestSubcase::Create<AdvancedUsageMultiStage>));
3621         addChild(new TestSubcase(m_context, "advanced-usage-draw-update-draw",
3622                                                          TestSubcase::Create<AdvancedUsageDrawUpdateDraw>));
3623         addChild(
3624                 new TestSubcase(m_context, "advanced-usage-many-counters", TestSubcase::Create<AdvancedUsageManyCounters>));
3625         addChild(
3626                 new TestSubcase(m_context, "advanced-usage-switch-programs", TestSubcase::Create<AdvancedUsageSwitchPrograms>));
3627         addChild(new TestSubcase(m_context, "advanced-usage-ubo", TestSubcase::Create<AdvancedUsageUBO>));
3628         addChild(new TestSubcase(m_context, "advanced-usage-many-draw-calls", TestSubcase::Create<AdvancedManyDrawCalls>));
3629         addChild(
3630                 new TestSubcase(m_context, "advanced-usage-many-draw-calls2", TestSubcase::Create<AdvancedManyDrawCalls2>));
3631         addChild(new TestSubcase(m_context, "advanced-usage-many-dispatches",
3632                                                          TestSubcase::Create<AdvancedUsageMultipleComputeDispatches>));
3633         addChild(new TestSubcase(m_context, "negative-api", TestSubcase::Create<NegativeAPI>));
3634         addChild(new TestSubcase(m_context, "negative-glsl", TestSubcase::Create<NegativeGLSL>));
3635         addChild(new TestSubcase(m_context, "negative-ssbo", TestSubcase::Create<NegativeSSBO>));
3636         addChild(new TestSubcase(m_context, "negative-ubo", TestSubcase::Create<NegativeUBO>));
3637         addChild(new TestSubcase(m_context, "negative-uniform", TestSubcase::Create<NegativeUniform>));
3638         addChild(new TestSubcase(m_context, "negative-array", TestSubcase::Create<NegativeArray>));
3639         addChild(new TestSubcase(m_context, "negative-arithmetic", TestSubcase::Create<NegativeArithmetic>));
3640 }
3641 }