092e68b13908bf6e01cd756fd0a48f7ef76bc3ba
[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 =
938                         static_cast<GLuint*>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 512 * sizeof(GLuint), GL_MAP_READ_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                 data = static_cast<GLuint*>(glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 32 * 4, GL_MAP_READ_BIT));
1804                 if (!CheckCounterValues(32, data, 7))
1805                         return ERROR;
1806                 glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
1807                 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
1808
1809                 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_buffer_[1]);
1810                 data = static_cast<GLuint*>(glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 32 * 4, GL_MAP_READ_BIT));
1811                 if (!CheckCounterValues(32, data, 45))
1812                         return ERROR;
1813                 glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
1814                 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
1815
1816                 if (!CheckFinalCounterValue(counter_buffer_[0], 0, 39))
1817                         return ERROR;
1818                 if (!CheckFinalCounterValue(counter_buffer_[1], 0, 45))
1819                         return ERROR;
1820
1821                 return NO_ERROR;
1822         }
1823         virtual long Cleanup()
1824         {
1825                 glDeleteBuffers(2, counter_buffer_);
1826                 glDeleteBuffers(2, xfb_buffer_);
1827                 glDeleteBuffers(1, &array_buffer_);
1828                 glDeleteVertexArrays(1, &vao_);
1829                 glDeleteProgram(prog_);
1830                 glUseProgram(0);
1831                 return NO_ERROR;
1832         }
1833 };
1834
1835 class AdvancedUsageMultiStage : public SACSubcaseBase
1836 {
1837         virtual std::string Title()
1838         {
1839                 return NL "Same atomic counter accessed from multiple shader stages";
1840         }
1841         virtual std::string Purpose()
1842         {
1843                 return NL "Same atomic counter is incremented (decremented) from two shader stages (VS and FS)." NL
1844                                   "Verify that this scenario works as expected. In particular ensure that all generated values are "
1845                                   "unique and" NL "final value in atomic counter buffer objects are as expected.";
1846         }
1847         virtual std::string Method()
1848         {
1849                 return NL "";
1850         }
1851         virtual std::string PassCriteria()
1852         {
1853                 return NL "";
1854         }
1855
1856         GLuint counter_buffer_;
1857         GLuint xfb_buffer_[2];
1858         GLuint vao_, vbo_;
1859         GLuint prog_;
1860         GLuint fbo_, rt_[2];
1861
1862         virtual long Setup()
1863         {
1864                 counter_buffer_ = 0;
1865                 xfb_buffer_[0] = xfb_buffer_[1] = 0;
1866                 vao_ = vbo_ = 0;
1867                 prog_           = 0;
1868                 fbo_ = rt_[0] = rt_[1] = 0;
1869                 return NO_ERROR;
1870         }
1871         virtual long Run()
1872         {
1873
1874                 GLint p1, p2, p3, p4;
1875                 glGetIntegerv(GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS, &p1);
1876                 glGetIntegerv(GL_MAX_VERTEX_ATOMIC_COUNTERS, &p2);
1877                 glGetIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS, &p3);
1878                 glGetIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTERS, &p4);
1879                 if (p1 < 8 || p2 < 2 || p3 < 8 || p4 < 2)
1880                 {
1881                         OutputNotSupported("GL_MAX_FRAGMENT/VERTEX_ATOMIC_COUNTER_BUFFERS or"
1882                                                            "GL_MAX_FRAGMENT/VERTEX_ATOMIC_COUNTERS are less than required");
1883                         return NOT_SUPPORTED;
1884                 }
1885
1886                 // create program
1887                 const char* src_vs =
1888                         "#version 310 es" NL "layout(location = 0) in vec4 i_vertex;" NL "flat out uint o_atomic_inc;" NL
1889                         "flat out uint o_atomic_dec;" NL "layout(binding = 1, offset = 16) uniform atomic_uint ac_counter_inc;" NL
1890                         "layout(binding = 7, offset = 128) uniform atomic_uint ac_counter_dec;" NL "void main() {" NL
1891                         "  gl_Position = i_vertex;" NL "  o_atomic_inc = atomicCounterIncrement(ac_counter_inc);" NL
1892                         "  o_atomic_dec = atomicCounterDecrement(ac_counter_dec);" NL "}";
1893                 const char* src_fs = "#version 310 es" NL "layout(location = 0) out uvec4 o_color[2];" NL
1894                                                          "layout(binding = 1, offset = 16) uniform atomic_uint ac_counter_inc;" NL
1895                                                          "layout(binding = 7, offset = 128) uniform atomic_uint ac_counter_dec;" NL
1896                                                          "void main() {" NL "  o_color[0] = uvec4(atomicCounterIncrement(ac_counter_inc));" NL
1897                                                          "  o_color[1] = uvec4(atomicCounterDecrement(ac_counter_dec));" NL "}";
1898                 prog_                              = CreateProgram(src_vs, src_fs, false);
1899                 const char* xfb_var[2] = { "o_atomic_inc", "o_atomic_dec" };
1900                 glTransformFeedbackVaryings(prog_, 2, xfb_var, GL_SEPARATE_ATTRIBS);
1901                 LinkProgram(prog_);
1902
1903                 // create atomic counter buffer
1904                 std::vector<GLuint> init_data(256, 100);
1905                 glGenBuffers(1, &counter_buffer_);
1906                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, counter_buffer_);
1907                 glBufferData(GL_ATOMIC_COUNTER_BUFFER, (GLsizeiptr)(init_data.size() * sizeof(GLuint)), &init_data[0],
1908                                          GL_DYNAMIC_COPY);
1909                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
1910
1911                 // create transform feedback buffers
1912                 glGenBuffers(2, xfb_buffer_);
1913                 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_buffer_[0]);
1914                 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 1000, NULL, GL_STREAM_COPY);
1915                 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_buffer_[1]);
1916                 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 1000, NULL, GL_STREAM_COPY);
1917                 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
1918
1919                 // create render targets
1920                 const int s = 8;
1921                 glGenTextures(2, rt_);
1922                 for (int i = 0; i < 2; ++i)
1923                 {
1924                         glBindTexture(GL_TEXTURE_2D, rt_[i]);
1925                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1926                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1927                         glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, s, s, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, NULL);
1928                         glBindTexture(GL_TEXTURE_2D, 0);
1929                 }
1930
1931                 // create fbo
1932                 glGenFramebuffers(1, &fbo_);
1933                 glBindFramebuffer(GL_FRAMEBUFFER, fbo_);
1934                 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt_[0], 0);
1935                 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, rt_[1], 0);
1936                 const GLenum draw_buffers[2] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
1937                 glDrawBuffers(2, draw_buffers);
1938                 glBindFramebuffer(GL_FRAMEBUFFER, 0);
1939
1940                 // create geometry
1941                 CreateTriangle(&vao_, &vbo_, NULL);
1942
1943                 // draw
1944                 glBindBufferRange(GL_ATOMIC_COUNTER_BUFFER, 1, counter_buffer_, 16, 32);
1945                 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 7, counter_buffer_);
1946                 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, xfb_buffer_[0]);
1947                 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 1, xfb_buffer_[1]);
1948                 glBindFramebuffer(GL_FRAMEBUFFER, fbo_);
1949                 glViewport(0, 0, s, s);
1950                 glUseProgram(prog_);
1951                 glBindVertexArray(vao_);
1952                 glBeginTransformFeedback(GL_TRIANGLES);
1953                 glDrawArrays(GL_TRIANGLES, 0, 3);
1954                 glEndTransformFeedback();
1955
1956                 // validate
1957                 UVec4 data[s * s + 3];
1958                 glReadBuffer(GL_COLOR_ATTACHMENT0);
1959                 glReadPixels(0, 0, s, s, GL_RGBA_INTEGER, GL_UNSIGNED_INT, data);
1960                 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_buffer_[0]);
1961                 GLuint* data2;
1962                 data2 = static_cast<GLuint*>(
1963                         glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 3 * sizeof(GLuint), GL_MAP_READ_BIT));
1964                 data[s * s]             = UVec4(data2[0]);
1965                 data[s * s + 1] = UVec4(data2[1]);
1966                 data[s * s + 2] = UVec4(data2[2]);
1967                 if (!CheckCounterValues(s * s + 3, data, 100))
1968                         return ERROR;
1969                 glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
1970                 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
1971
1972                 glReadBuffer(GL_COLOR_ATTACHMENT1);
1973                 glReadPixels(0, 0, s, s, GL_RGBA_INTEGER, GL_UNSIGNED_INT, data);
1974                 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_buffer_[1]);
1975                 data2 = static_cast<GLuint*>(
1976                         glMapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 3 * sizeof(GLuint), GL_MAP_READ_BIT));
1977                 data[s * s]             = UVec4(data2[0]);
1978                 data[s * s + 1] = UVec4(data2[1]);
1979                 data[s * s + 2] = UVec4(data2[2]);
1980                 if (!CheckCounterValues(s * s + 3, data, 33))
1981                         return ERROR;
1982                 glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
1983                 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
1984
1985                 if (!CheckFinalCounterValue(counter_buffer_, 32, 167))
1986                         return ERROR;
1987                 if (!CheckFinalCounterValue(counter_buffer_, 128, 33))
1988                         return ERROR;
1989
1990                 return NO_ERROR;
1991         }
1992         virtual long Cleanup()
1993         {
1994                 glDeleteFramebuffers(1, &fbo_);
1995                 glDeleteTextures(2, rt_);
1996                 glViewport(0, 0, getWindowWidth(), getWindowHeight());
1997                 glDeleteBuffers(1, &counter_buffer_);
1998                 glDeleteBuffers(2, xfb_buffer_);
1999                 glDeleteVertexArrays(1, &vao_);
2000                 glDeleteBuffers(1, &vbo_);
2001                 glDeleteProgram(prog_);
2002                 glUseProgram(0);
2003                 return NO_ERROR;
2004         }
2005 };
2006
2007 class AdvancedUsageDrawUpdateDraw : public SACSubcaseBase
2008 {
2009         virtual std::string Title()
2010         {
2011                 return NL "Update via Draw Call and update via MapBufferRange";
2012         }
2013         virtual std::string Purpose()
2014         {
2015                 return NL "1. Create atomic counter buffers and init them with start values." NL
2016                                   "2. Increment (decrement) buffer values in the shader." NL
2017                                   "3. Map buffers with MapBufferRange command. Increment (decrement) buffer values manually." NL
2018                                   "4. Unmap buffers with UnmapBuffer command." NL
2019                                   "5. Again increment (decrement) buffer values in the shader." NL
2020                                   "Verify that this scenario works as expected and final values in the buffer objects are correct.";
2021         }
2022         virtual std::string Method()
2023         {
2024                 return NL "";
2025         }
2026         virtual std::string PassCriteria()
2027         {
2028                 return NL "";
2029         }
2030
2031         GLuint counter_buffer_;
2032         GLuint vao_, vbo_;
2033         GLuint prog_, prog2_;
2034         GLuint fbo_, rt_[2];
2035
2036         virtual long Setup()
2037         {
2038                 counter_buffer_ = 0;
2039                 vao_ = vbo_ = 0;
2040                 prog_           = 0;
2041                 prog2_          = 0;
2042                 fbo_ = rt_[0] = rt_[1] = 0;
2043                 return NO_ERROR;
2044         }
2045         virtual long Run()
2046         {
2047
2048                 GLint p1, p2;
2049                 glGetIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS, &p1);
2050                 glGetIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTERS, &p2);
2051                 if (p1 < 1 || p2 < 2)
2052                 {
2053                         OutputNotSupported(
2054                                 "GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS or GL_MAX_FRAGMENT_ATOMIC_COUNTERS are less than required");
2055                         return NOT_SUPPORTED;
2056                 }
2057
2058                 // create program
2059                 const char* src_vs = "#version 310 es" NL "layout(location = 0) in vec4 i_vertex;" NL "void main() {" NL
2060                                                          "  gl_Position = i_vertex;" NL "}";
2061                 const char* src_fs = "#version 310 es" NL "layout(location = 0) out uvec4 o_color[2];" NL
2062                                                          "layout(binding = 0) uniform atomic_uint ac_counter[2];" NL "void main() {" NL
2063                                                          "  o_color[0] = uvec4(atomicCounterIncrement(ac_counter[0]));" NL
2064                                                          "  o_color[1] = uvec4(atomicCounterDecrement(ac_counter[1]));" NL "}";
2065                 const char* src_fs2 = "#version 310 es" NL "layout(location = 0) out uvec4 o_color[2];" NL
2066                                                           "layout(binding = 0) uniform atomic_uint ac_counter[2];" NL "void main() {" NL
2067                                                           "  o_color[0] = uvec4(atomicCounter(ac_counter[0]));" NL
2068                                                           "  o_color[1] = uvec4(atomicCounter(ac_counter[1]));" NL "}";
2069                 prog_  = CreateProgram(src_vs, src_fs, true);
2070                 prog2_ = CreateProgram(src_vs, src_fs2, true);
2071
2072                 // create atomic counter buffer
2073                 glGenBuffers(1, &counter_buffer_);
2074                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, counter_buffer_);
2075                 glBufferData(GL_ATOMIC_COUNTER_BUFFER, 8, NULL, GL_DYNAMIC_COPY);
2076                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
2077
2078                 // create render targets
2079                 const int s = 8;
2080                 glGenTextures(2, rt_);
2081
2082                 for (int i = 0; i < 2; ++i)
2083                 {
2084                         glBindTexture(GL_TEXTURE_2D, rt_[i]);
2085                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2086                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2087                         glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, s, s, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, NULL);
2088                         glBindTexture(GL_TEXTURE_2D, 0);
2089                 }
2090
2091                 // create fbo
2092                 glGenFramebuffers(1, &fbo_);
2093                 glBindFramebuffer(GL_FRAMEBUFFER, fbo_);
2094                 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt_[0], 0);
2095                 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, rt_[1], 0);
2096                 const GLenum draw_buffers[2] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
2097                 glDrawBuffers(2, draw_buffers);
2098                 glBindFramebuffer(GL_FRAMEBUFFER, 0);
2099
2100                 // create geometry
2101                 CreateQuad(&vao_, &vbo_, NULL);
2102
2103                 // init counter buffer
2104                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, counter_buffer_);
2105                 unsigned int* ptr = static_cast<unsigned int*>(
2106                         glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, 8, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT));
2107                 *ptr++ = 256;
2108                 *ptr++ = 256;
2109                 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
2110
2111                 // draw
2112                 glBindFramebuffer(GL_FRAMEBUFFER, fbo_);
2113                 glViewport(0, 0, s, s);
2114                 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, counter_buffer_);
2115                 glUseProgram(prog_);
2116                 glBindVertexArray(vao_);
2117                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2118
2119                 // update counter buffer
2120                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, counter_buffer_);
2121                 ptr = static_cast<unsigned int*>(
2122                         glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, 8, GL_MAP_WRITE_BIT | GL_MAP_READ_BIT));
2123                 *ptr++ += 512;
2124                 *ptr++ += 1024;
2125                 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
2126
2127                 // draw
2128                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2129                 glMemoryBarrier(GL_ATOMIC_COUNTER_BARRIER_BIT);
2130
2131                 // draw
2132                 glUseProgram(prog2_);
2133                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2134
2135                 // validate
2136                 UVec4 data[s * s];
2137                 glReadBuffer(GL_COLOR_ATTACHMENT0);
2138                 glReadPixels(0, 0, s, s, GL_RGBA_INTEGER, GL_UNSIGNED_INT, data);
2139                 for (int i = 0; i < s * s; ++i)
2140                 {
2141                         if (data[i].x() != 896)
2142                         {
2143                                 Output("Counter value is %u should be %u.\n", data[i].x(), 896);
2144                                 return ERROR;
2145                         }
2146                 }
2147
2148                 glReadBuffer(GL_COLOR_ATTACHMENT1);
2149                 glReadPixels(0, 0, s, s, GL_RGBA_INTEGER, GL_UNSIGNED_INT, data);
2150                 for (int i = 0; i < s * s; ++i)
2151                 {
2152                         if (data[i].x() != 1152)
2153                         {
2154                                 Output("Counter value is %u should be %u.\n", data[i].x(), 896);
2155                                 return ERROR;
2156                         }
2157                 }
2158
2159                 if (!CheckFinalCounterValue(counter_buffer_, 0, 896))
2160                         return ERROR;
2161                 if (!CheckFinalCounterValue(counter_buffer_, 4, 1152))
2162                         return ERROR;
2163
2164                 return NO_ERROR;
2165         }
2166         virtual long Cleanup()
2167         {
2168                 glDeleteFramebuffers(1, &fbo_);
2169                 glDeleteTextures(2, rt_);
2170                 glViewport(0, 0, getWindowWidth(), getWindowHeight());
2171                 glDeleteBuffers(1, &counter_buffer_);
2172                 glDeleteVertexArrays(1, &vao_);
2173                 glDeleteBuffers(1, &vbo_);
2174                 glDeleteProgram(prog_);
2175                 glDeleteProgram(prog2_);
2176                 glUseProgram(0);
2177                 return NO_ERROR;
2178         }
2179 };
2180
2181 class AdvancedUsageManyCounters : public BasicUsageCS
2182 {
2183         virtual std::string Title()
2184         {
2185                 return NL "Large atomic counters array indexed with uniforms";
2186         }
2187         virtual std::string Purpose()
2188         {
2189                 return NL "Verify that large atomic counters array works as expected when indexed with dynamically uniform "
2190                                   "expressions." NL
2191                                   "Built-ins tested: atomicCounterIncrement, atomicCounterDecrement and atomicCounter.";
2192         }
2193         virtual std::string Method()
2194         {
2195                 return NL "";
2196         }
2197         virtual std::string PassCriteria()
2198         {
2199                 return NL "";
2200         }
2201
2202         GLuint counter_buffer_, m_ssbo;
2203         GLuint prog_;
2204
2205         virtual long Setup()
2206         {
2207                 counter_buffer_ = 0;
2208                 m_ssbo                  = 0;
2209                 prog_                   = 0;
2210                 return NO_ERROR;
2211         }
2212
2213         virtual long Run()
2214         {
2215                 // create program
2216                 const char* glsl_cs = NL
2217                         "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;" NL "layout(std430) buffer Output {" NL
2218                         "  mediump uvec4 data1[64];" NL "  mediump uvec4 data2[64];" NL "  mediump uvec4 data3[64];" NL
2219                         "  mediump uvec4 data4[64];" NL "  mediump uvec4 data5[64];" NL "  mediump uvec4 data6[64];" NL
2220                         "  mediump uvec4 data7[64];" NL "  mediump uvec4 data8[64];" NL "} g_out;" NL
2221                         "uniform mediump int u_active_counters[8];" NL "layout(binding = 0) uniform atomic_uint ac_counter[8];" NL
2222                         "void main() {" NL "  mediump uint offset = 8u * gl_GlobalInvocationID.y + gl_GlobalInvocationID.x;" NL
2223                         "  g_out.data1[offset] = uvec4(atomicCounterIncrement(ac_counter[u_active_counters[0]]));" NL
2224                         "  g_out.data2[offset] = uvec4(atomicCounterDecrement(ac_counter[u_active_counters[1]]));" NL
2225                         "  g_out.data3[offset] = uvec4(atomicCounter(ac_counter[u_active_counters[2]]));" NL
2226                         "  g_out.data4[offset] = uvec4(atomicCounterIncrement(ac_counter[u_active_counters[3]]));" NL
2227                         "  g_out.data5[offset] = uvec4(atomicCounterDecrement(ac_counter[u_active_counters[4]]));" NL
2228                         "  g_out.data6[offset] = uvec4(atomicCounter(ac_counter[u_active_counters[5]]));" NL
2229                         "  g_out.data7[offset] = uvec4(atomicCounterIncrement(ac_counter[u_active_counters[6]]));" NL
2230                         "  g_out.data8[offset] = uvec4(atomicCounterIncrement(ac_counter[u_active_counters[7]]));" NL "}";
2231
2232                 prog_ = CreateComputeProgram(glsl_cs);
2233                 glLinkProgram(prog_);
2234                 if (!CheckProgram(prog_))
2235                         return ERROR;
2236
2237                 // create atomic counter buffer
2238                 std::vector<GLuint> init_data(1024, 1000);
2239                 glGenBuffers(1, &counter_buffer_);
2240                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, counter_buffer_);
2241                 glBufferData(GL_ATOMIC_COUNTER_BUFFER, 1024 * sizeof(GLuint), &init_data[0], GL_DYNAMIC_COPY);
2242                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
2243
2244                 glGenBuffers(1, &m_ssbo);
2245                 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_ssbo);
2246                 glBufferData(GL_SHADER_STORAGE_BUFFER, 8 * 64 * sizeof(UVec4), NULL, GL_DYNAMIC_DRAW);
2247                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
2248
2249                 // set uniforms
2250                 glUseProgram(prog_);
2251                 glUniform1i(glGetUniformLocation(prog_, "u_active_counters[0]"), 0);
2252                 glUniform1i(glGetUniformLocation(prog_, "u_active_counters[1]"), 1);
2253                 glUniform1i(glGetUniformLocation(prog_, "u_active_counters[2]"), 2);
2254                 glUniform1i(glGetUniformLocation(prog_, "u_active_counters[3]"), 3);
2255                 glUniform1i(glGetUniformLocation(prog_, "u_active_counters[4]"), 4);
2256                 glUniform1i(glGetUniformLocation(prog_, "u_active_counters[5]"), 5);
2257                 glUniform1i(glGetUniformLocation(prog_, "u_active_counters[6]"), 6);
2258                 glUniform1i(glGetUniformLocation(prog_, "u_active_counters[7]"), 7);
2259
2260                 // dispatch
2261                 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, counter_buffer_);
2262                 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_ssbo);
2263                 glDispatchCompute(8, 8, 1);
2264
2265                 // validate
2266                 glMemoryBarrier(GL_ATOMIC_COUNTER_BARRIER_BIT | GL_SHADER_STORAGE_BARRIER_BIT);
2267                 UVec4* data;
2268                 long   error = NO_ERROR;
2269
2270                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_ssbo);
2271                 data = static_cast<UVec4*>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 64 * sizeof(UVec4), GL_MAP_READ_BIT));
2272                 if (!CheckCounterValues(8 * 8, data, 1000))
2273                         error = ERROR;
2274                 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2275                 if (!CheckFinalCounterValue(counter_buffer_, 0, 1064))
2276                         error = ERROR;
2277
2278                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_ssbo);
2279                 data = static_cast<UVec4*>(
2280                         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 64 * sizeof(UVec4), 64 * sizeof(UVec4), GL_MAP_READ_BIT));
2281                 if (!CheckCounterValues(8 * 8, data, 1000 - 64))
2282                         error = ERROR;
2283                 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2284                 if (!CheckFinalCounterValue(counter_buffer_, 1 * sizeof(GLuint), 1000 - 64))
2285                         error = ERROR;
2286
2287                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_ssbo);
2288                 data = static_cast<UVec4*>(
2289                         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 64 * sizeof(UVec4) * 2, 64 * sizeof(UVec4), GL_MAP_READ_BIT));
2290                 for (int i = 0; i < 8 * 8; ++i)
2291                         if (data[i].x() != 1000)
2292                                 error = ERROR;
2293                 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2294                 if (!CheckFinalCounterValue(counter_buffer_, 2 * sizeof(GLuint), 1000))
2295                         error = ERROR;
2296
2297                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_ssbo);
2298                 data = static_cast<UVec4*>(
2299                         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 64 * sizeof(UVec4) * 3, 64 * sizeof(UVec4), GL_MAP_READ_BIT));
2300                 if (!CheckCounterValues(8 * 8, data, 1000))
2301                         error = ERROR;
2302                 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2303                 if (!CheckFinalCounterValue(counter_buffer_, 3 * sizeof(GLuint), 1064))
2304                         error = ERROR;
2305
2306                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_ssbo);
2307                 data = static_cast<UVec4*>(
2308                         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 64 * sizeof(UVec4) * 4, 64 * sizeof(UVec4), GL_MAP_READ_BIT));
2309                 if (!CheckCounterValues(8 * 8, data, 1000 - 64))
2310                         error = ERROR;
2311                 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2312                 if (!CheckFinalCounterValue(counter_buffer_, 4 * sizeof(GLuint), 1000 - 64))
2313                         error = ERROR;
2314
2315                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_ssbo);
2316                 data = static_cast<UVec4*>(
2317                         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 64 * sizeof(UVec4) * 5, 64 * sizeof(UVec4), GL_MAP_READ_BIT));
2318                 for (int i = 0; i < 8 * 8; ++i)
2319                         if (data[i].x() != 1000)
2320                                 error = ERROR;
2321                 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2322                 if (!CheckFinalCounterValue(counter_buffer_, 5 * sizeof(GLuint), 1000))
2323                         error = ERROR;
2324
2325                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_ssbo);
2326                 data = static_cast<UVec4*>(
2327                         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 64 * sizeof(UVec4) * 6, 64 * sizeof(UVec4), GL_MAP_READ_BIT));
2328                 if (!CheckCounterValues(8 * 8, data, 1000))
2329                         error = ERROR;
2330                 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2331                 if (!CheckFinalCounterValue(counter_buffer_, 6 * sizeof(GLuint), 1064))
2332                         error = ERROR;
2333
2334                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_ssbo);
2335                 data = static_cast<UVec4*>(
2336                         glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 64 * sizeof(UVec4) * 7, 64 * sizeof(UVec4), GL_MAP_READ_BIT));
2337                 if (!CheckCounterValues(8 * 8, data, 1000))
2338                         error = ERROR;
2339                 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2340                 if (!CheckFinalCounterValue(counter_buffer_, 7 * sizeof(GLuint), 1064))
2341                         error = ERROR;
2342
2343                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
2344                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
2345                 return error;
2346         }
2347
2348         virtual long Cleanup()
2349         {
2350                 glDeleteBuffers(1, &counter_buffer_);
2351                 glDeleteBuffers(1, &m_ssbo);
2352                 glDeleteProgram(prog_);
2353                 glUseProgram(0);
2354                 return NO_ERROR;
2355         }
2356 };
2357
2358 class AdvancedUsageSwitchPrograms : public SACSubcaseBase
2359 {
2360         virtual std::string Title()
2361         {
2362                 return NL "Switching several program objects with different atomic counters with different bindings";
2363         }
2364         virtual std::string Purpose()
2365         {
2366                 return NL "Verify that each program upadate atomic counter buffer object in appropriate binding point.";
2367         }
2368         virtual std::string Method()
2369         {
2370                 return NL "";
2371         }
2372         virtual std::string PassCriteria()
2373         {
2374                 return NL "";
2375         }
2376
2377         GLuint counter_buffer_[8];
2378         GLuint xfb_buffer_;
2379         GLuint vao_, vbo_;
2380         GLuint prog_[8];
2381         GLuint fbo_, rt_;
2382
2383         std::string GenVSSrc(int binding, int offset)
2384         {
2385                 std::ostringstream os;
2386                 os << "#version 310 es" NL "layout(location = 0) in vec4 i_vertex;" NL "flat out uvec4 o_atomic_value;" NL
2387                           "layout(binding = "
2388                    << binding << ", offset = " << offset
2389                    << ") uniform atomic_uint ac_counter_vs;" NL "void main() {" NL "  gl_Position = i_vertex;" NL
2390                           "  o_atomic_value = uvec4(atomicCounterIncrement(ac_counter_vs));" NL "}";
2391                 return os.str();
2392         }
2393         std::string GenFSSrc(int binding, int offset)
2394         {
2395                 std::ostringstream os;
2396                 os << "#version 310 es" NL "layout(location = 0) out uvec4 o_color;" NL "layout(binding = " << binding
2397                    << ", offset = " << offset << ") uniform atomic_uint ac_counter_fs;" NL "void main() {" NL
2398                                                                                  "  o_color = uvec4(atomicCounterIncrement(ac_counter_fs));" NL "}";
2399                 return os.str();
2400         }
2401         virtual long Setup()
2402         {
2403                 memset(counter_buffer_, 0, sizeof(counter_buffer_));
2404                 xfb_buffer_ = 0;
2405                 vao_ = vbo_ = 0;
2406                 memset(prog_, 0, sizeof(prog_));
2407                 fbo_ = rt_ = 0;
2408                 return NO_ERROR;
2409         }
2410         virtual long Run()
2411         {
2412
2413                 GLint p1, p2, p3, p4;
2414                 glGetIntegerv(GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS, &p1);
2415                 glGetIntegerv(GL_MAX_VERTEX_ATOMIC_COUNTERS, &p2);
2416                 glGetIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS, &p3);
2417                 glGetIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTERS, &p4);
2418                 if (p1 < 8 || p2 < 1 || p3 < 8 || p4 < 1)
2419                 {
2420                         OutputNotSupported("GL_MAX_*_ATOMIC_COUNTER_BUFFERS or GL_MAX_*_ATOMIC_COUNTERS are less than required");
2421                         return NOT_SUPPORTED;
2422                 }
2423
2424                 // create programs
2425                 for (int i = 0; i < 8; ++i)
2426                 {
2427                         std::string vs_str  = GenVSSrc(i, i * 8);
2428                         std::string fs_str  = GenFSSrc(7 - i, 128 + i * 16);
2429                         const char* src_vs  = vs_str.c_str();
2430                         const char* src_fs  = fs_str.c_str();
2431                         prog_[i]                        = CreateProgram(src_vs, src_fs, false);
2432                         const char* xfb_var = "o_atomic_value";
2433                         glTransformFeedbackVaryings(prog_[i], 1, &xfb_var, GL_SEPARATE_ATTRIBS);
2434                         LinkProgram(prog_[i]);
2435                 }
2436
2437                 // create atomic counter buffers
2438                 glGenBuffers(8, counter_buffer_);
2439                 for (int i = 0; i < 8; ++i)
2440                 {
2441                         std::vector<GLuint> init_data(256);
2442                         glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, counter_buffer_[i]);
2443                         glBufferData(GL_ATOMIC_COUNTER_BUFFER, (GLsizeiptr)(init_data.size() * sizeof(GLuint)), &init_data[0],
2444                                                  GL_DYNAMIC_COPY);
2445                 }
2446                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
2447
2448                 // create transform feedback buffer
2449                 glGenBuffers(1, &xfb_buffer_);
2450                 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_buffer_);
2451                 glBufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 1000, NULL, GL_STREAM_COPY);
2452                 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
2453
2454                 // create render target
2455                 const int s = 8;
2456                 glGenTextures(1, &rt_);
2457                 glBindTexture(GL_TEXTURE_2D, rt_);
2458                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2459                 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2460                 glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, s, s, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, NULL);
2461                 glBindTexture(GL_TEXTURE_2D, 0);
2462
2463                 // create fbo
2464                 glGenFramebuffers(1, &fbo_);
2465                 glBindFramebuffer(GL_FRAMEBUFFER, fbo_);
2466                 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt_, 0);
2467                 glBindFramebuffer(GL_FRAMEBUFFER, 0);
2468
2469                 // create geometry
2470                 CreateTriangle(&vao_, &vbo_, NULL);
2471
2472                 // draw
2473                 for (GLuint i = 0; i < 8; ++i)
2474                 {
2475                         glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, i, counter_buffer_[i]);
2476                 }
2477                 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, xfb_buffer_);
2478                 glBindFramebuffer(GL_FRAMEBUFFER, fbo_);
2479                 glViewport(0, 0, s, s);
2480                 glBindVertexArray(vao_);
2481
2482                 for (int i = 0; i < 8; ++i)
2483                 {
2484                         glUseProgram(prog_[i]);
2485                         glBeginTransformFeedback(GL_TRIANGLES);
2486                         glDrawArrays(GL_TRIANGLES, 0, 3);
2487                         glEndTransformFeedback();
2488                         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2489
2490                         if (!CheckFinalCounterValue(counter_buffer_[i], i * 8, 3))
2491                                 return ERROR;
2492                         if (!CheckFinalCounterValue(counter_buffer_[7 - i], 128 + i * 16, 64))
2493                                 return ERROR;
2494                 }
2495                 return NO_ERROR;
2496         }
2497         virtual long Cleanup()
2498         {
2499                 glDeleteFramebuffers(1, &fbo_);
2500                 glDeleteTextures(1, &rt_);
2501                 glViewport(0, 0, getWindowWidth(), getWindowHeight());
2502                 glDeleteBuffers(8, counter_buffer_);
2503                 glDeleteBuffers(1, &xfb_buffer_);
2504                 glDeleteVertexArrays(1, &vao_);
2505                 glDeleteBuffers(1, &vbo_);
2506                 for (int i = 0; i < 8; ++i)
2507                         glDeleteProgram(prog_[i]);
2508                 glUseProgram(0);
2509                 return NO_ERROR;
2510         }
2511 };
2512
2513 class AdvancedUsageUBO : public BasicUsageCS
2514 {
2515         virtual std::string Title()
2516         {
2517                 return NL "Atomic Counters used to access Uniform Buffer Objects";
2518         }
2519         virtual std::string Purpose()
2520         {
2521                 return NL "Atomic counters are used to access UBOs. In that way each shader invocation can access UBO at "
2522                                   "unique offset." NL
2523                                   "This scenario is a base for some practical algorithms. Verify that it works as expected.";
2524         }
2525         virtual std::string Method()
2526         {
2527                 return NL "";
2528         }
2529         virtual std::string PassCriteria()
2530         {
2531                 return NL "";
2532         }
2533
2534         GLuint counter_buffer_, m_ssbo;
2535         GLuint uniform_buffer_;
2536         GLuint prog_;
2537
2538         virtual long Setup()
2539         {
2540                 counter_buffer_ = 0;
2541                 uniform_buffer_ = 0;
2542                 m_ssbo                  = 0;
2543                 prog_                   = 0;
2544                 return NO_ERROR;
2545         }
2546
2547         virtual long Run()
2548         {
2549                 // create program
2550                 const char* glsl_cs =
2551                         NL "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;" NL "layout(std430) buffer Output {" NL
2552                            "  mediump uvec4 color[256];" NL "} g_out;" NL
2553                            "layout(binding = 0, offset = 0) uniform atomic_uint ac_counter;" NL "layout(std140) uniform Data {" NL
2554                            "  mediump uint index[256];" NL "} ub_data;" NL "void main() {" NL
2555                            "  mediump uint offset = 16u * gl_GlobalInvocationID.y + gl_GlobalInvocationID.x;" NL
2556                            "  g_out.color[offset] = uvec4(ub_data.index[atomicCounterIncrement(ac_counter)]);" NL "}";
2557                 prog_ = CreateComputeProgram(glsl_cs);
2558                 glLinkProgram(prog_);
2559                 if (!CheckProgram(prog_))
2560                         return ERROR;
2561                 glUniformBlockBinding(prog_, glGetUniformBlockIndex(prog_, "Data"), 1);
2562
2563                 // create atomic counter buffer
2564                 const unsigned int z = 0;
2565                 glGenBuffers(1, &counter_buffer_);
2566                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, counter_buffer_);
2567                 glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(z), &z, GL_DYNAMIC_COPY);
2568                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
2569
2570                 // create uniform buffer
2571                 std::vector<UVec4> init_data(256);
2572                 for (GLuint i   = 0; i < 256; ++i)
2573                         init_data[i] = UVec4(i);
2574                 glGenBuffers(1, &uniform_buffer_);
2575                 glBindBuffer(GL_UNIFORM_BUFFER, uniform_buffer_);
2576                 glBufferData(GL_UNIFORM_BUFFER, (GLsizeiptr)(sizeof(UVec4) * init_data.size()), &init_data[0], GL_DYNAMIC_COPY);
2577                 glBindBuffer(GL_UNIFORM_BUFFER, 0);
2578
2579                 glGenBuffers(1, &m_ssbo);
2580                 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_ssbo);
2581                 glBufferData(GL_SHADER_STORAGE_BUFFER, 256 * sizeof(UVec4), NULL, GL_DYNAMIC_DRAW);
2582                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
2583
2584                 // draw
2585                 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, counter_buffer_);
2586                 glBindBufferBase(GL_UNIFORM_BUFFER, 1, uniform_buffer_);
2587                 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_ssbo);
2588                 glUseProgram(prog_);
2589                 glDispatchCompute(16, 16, 1);
2590
2591                 // validate
2592                 UVec4* data;
2593                 long   error = NO_ERROR;
2594                 glMemoryBarrier(GL_UNIFORM_BARRIER_BIT | GL_SHADER_STORAGE_BARRIER_BIT | GL_ATOMIC_COUNTER_BARRIER_BIT);
2595
2596                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_ssbo);
2597                 data = static_cast<UVec4*>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 256 * sizeof(UVec4), GL_MAP_READ_BIT));
2598                 if (!CheckCounterValues(16 * 16, data, 0))
2599                         error = ERROR;
2600                 if (!CheckFinalCounterValue(counter_buffer_, 0, 256))
2601                         error = ERROR;
2602                 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2603
2604                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
2605                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
2606
2607                 return error;
2608         }
2609
2610         virtual long Cleanup()
2611         {
2612                 glDeleteBuffers(1, &counter_buffer_);
2613                 glDeleteBuffers(1, &uniform_buffer_);
2614                 glDeleteBuffers(1, &m_ssbo);
2615                 glDeleteProgram(prog_);
2616                 glUseProgram(0);
2617                 return NO_ERROR;
2618         }
2619 };
2620
2621 class NegativeAPI : public SACSubcaseBase
2622 {
2623         virtual std::string Title()
2624         {
2625                 return NL "NegativeAPI";
2626         }
2627         virtual std::string Purpose()
2628         {
2629                 return NL "Verify errors reported by BindBuffer* commands.";
2630         }
2631         virtual std::string Method()
2632         {
2633                 return NL "";
2634         }
2635         virtual std::string PassCriteria()
2636         {
2637                 return NL "";
2638         }
2639
2640         GLuint buffer;
2641
2642         virtual long Setup()
2643         {
2644                 return NO_ERROR;
2645         }
2646         virtual long Run()
2647         {
2648                 long  error = NO_ERROR;
2649                 GLint res;
2650                 glGetIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, &res);
2651                 glGenBuffers(1, &buffer);
2652                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, buffer);
2653                 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, res, buffer);
2654                 if (glGetError() != GL_INVALID_VALUE)
2655                 {
2656                         Output("glBindBufferBase should generate INVALID_VALUE when"
2657                                    " index is greater than or equal GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS.\n");
2658                         error = ERROR;
2659                 }
2660                 glBindBufferRange(GL_ATOMIC_COUNTER_BUFFER, res, buffer, 0, 4);
2661                 if (glGetError() != GL_INVALID_VALUE)
2662                 {
2663                         Output("glBindBufferRange should generate INVALID_VALUE when"
2664                                    " index is greater than or equal GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS.\n");
2665                         error = ERROR;
2666                 }
2667                 glBindBufferRange(GL_ATOMIC_COUNTER_BUFFER, res - 1, buffer, 3, 4);
2668                 if (glGetError() != GL_INVALID_VALUE)
2669                 {
2670                         Output("glBindBufferRange should generate INVALID_VALUE when"
2671                                    " <offset> is not a multiple of four\n");
2672                         error = ERROR;
2673                 }
2674                 return error;
2675         }
2676         virtual long Cleanup()
2677         {
2678                 glDeleteBuffers(1, &buffer);
2679                 return NO_ERROR;
2680         }
2681 };
2682
2683 class NegativeGLSL : public BasicUsageCS
2684 {
2685         virtual std::string Title()
2686         {
2687                 return NL "GLSL errors";
2688         }
2689         virtual std::string Purpose()
2690         {
2691                 return NL "Verify that two different atomic counter uniforms with same binding cannot share same offset value.";
2692         }
2693         virtual std::string Method()
2694         {
2695                 return NL "";
2696         }
2697         virtual std::string PassCriteria()
2698         {
2699                 return NL "";
2700         }
2701
2702         GLuint prog_;
2703
2704         virtual long Setup()
2705         {
2706                 prog_ = 0;
2707                 return NO_ERROR;
2708         }
2709
2710         virtual long Run()
2711         {
2712                 const char* const glsl_cs = NL
2713                         "layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;" NL
2714                         "layout(binding = 0, offset = 4) uniform atomic_uint ac_counter_inc;" NL
2715                         "layout(binding = 0, offset = 4) uniform atomic_uint ac_counter_dec;" NL "layout(std430) buffer Output {" NL
2716                         "  mediump uint data_inc[256];" NL "  mediump uint data_dec[256];" NL "} g_out;" NL "void main() {" NL
2717                         "  mediump uint offset = 32u * gl_GlobalInvocationID.y + gl_GlobalInvocationID.x;" NL
2718                         "  g_out.data_inc[offset] = atomicCounterIncrement(ac_counter_inc);" NL
2719                         "  g_out.data_dec[offset] = atomicCounterDecrement(ac_counter_dec);" NL "}";
2720
2721                 prog_ = CreateComputeProgram(glsl_cs);
2722                 glLinkProgram(prog_);
2723                 if (CheckProgram(prog_))
2724                 {
2725                         Output("Link should fail because ac_counter0 and ac_counter2 uses same binding and same offset.\n");
2726                         return ERROR;
2727                 }
2728                 return NO_ERROR;
2729         }
2730         virtual long Cleanup()
2731         {
2732                 glDeleteProgram(prog_);
2733                 return NO_ERROR;
2734         }
2735 };
2736
2737 class AdvancedManyDrawCalls : public SACSubcaseBase
2738 {
2739         virtual std::string Title()
2740         {
2741                 return NL "Atomic Counters usage in multiple draw calls";
2742         }
2743         virtual std::string Purpose()
2744         {
2745                 return NL "Verify atomic counters behaviour across multiple draw calls.";
2746         }
2747         virtual std::string Method()
2748         {
2749                 return NL "";
2750         }
2751         virtual std::string PassCriteria()
2752         {
2753                 return NL "";
2754         }
2755
2756         GLuint counter_buffer_;
2757         GLuint vao_, vbo_;
2758         GLuint prog_;
2759         GLuint fbo_, rt_[2];
2760
2761         virtual long Setup()
2762         {
2763                 counter_buffer_ = 0;
2764                 vao_ = vbo_ = 0;
2765                 prog_           = 0;
2766                 fbo_ = rt_[0] = rt_[1] = 0;
2767                 return NO_ERROR;
2768         }
2769         virtual long Run()
2770         {
2771
2772                 GLint p1, p2;
2773                 glGetIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS, &p1);
2774                 glGetIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTERS, &p2);
2775                 if (p1 < 1 || p2 < 2)
2776                 {
2777                         OutputNotSupported(
2778                                 "GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS or GL_MAX_FRAGMENT_ATOMIC_COUNTERS are less than required");
2779                         return NOT_SUPPORTED;
2780                 }
2781
2782                 // create program
2783                 const char* src_vs = "#version 310 es" NL "layout(location = 0) in vec4 i_vertex;" NL "void main() {" NL
2784                                                          "  gl_Position = i_vertex;" NL "}";
2785                 const char* src_fs = "#version 310 es" NL "layout(location = 0) out uvec4 o_color[2];" NL
2786                                                          "layout(binding = 0, offset = 0) uniform atomic_uint ac_counter_inc;" NL
2787                                                          "layout(binding = 0, offset = 4) uniform atomic_uint ac_counter_dec;" NL "void main() {" NL
2788                                                          "  o_color[0] = uvec4(atomicCounterIncrement(ac_counter_inc));" NL
2789                                                          "  o_color[1] = uvec4(atomicCounterDecrement(ac_counter_dec));" NL "}";
2790                 prog_ = CreateProgram(src_vs, src_fs, true);
2791
2792                 // create atomic counter buffer
2793                 glGenBuffers(1, &counter_buffer_);
2794                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, counter_buffer_);
2795                 glBufferData(GL_ATOMIC_COUNTER_BUFFER, 8, NULL, GL_DYNAMIC_COPY);
2796                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
2797
2798                 // create render targets
2799                 const int s = 8;
2800                 glGenTextures(2, rt_);
2801
2802                 for (int i = 0; i < 2; ++i)
2803                 {
2804                         glBindTexture(GL_TEXTURE_2D, rt_[i]);
2805                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2806                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2807                         glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, s, s, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, NULL);
2808                         glBindTexture(GL_TEXTURE_2D, 0);
2809                 }
2810
2811                 // create fbo
2812                 glGenFramebuffers(1, &fbo_);
2813                 glBindFramebuffer(GL_FRAMEBUFFER, fbo_);
2814                 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, rt_[0], 0);
2815                 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, rt_[1], 0);
2816                 const GLenum draw_buffers[2] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
2817                 glDrawBuffers(2, draw_buffers);
2818                 glBindFramebuffer(GL_FRAMEBUFFER, 0);
2819
2820                 // create geometry
2821                 CreateQuad(&vao_, &vbo_, NULL);
2822
2823                 // init counter buffer
2824                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, counter_buffer_);
2825                 unsigned int* ptr = static_cast<unsigned int*>(
2826                         glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, 8, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT));
2827                 *ptr++ = 0;
2828                 *ptr++ = 256;
2829                 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
2830
2831                 // draw
2832                 glBindFramebuffer(GL_FRAMEBUFFER, fbo_);
2833                 glViewport(0, 0, s, s);
2834                 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, counter_buffer_);
2835                 glUseProgram(prog_);
2836                 glBindVertexArray(vao_);
2837
2838                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2839                 glMemoryBarrier(GL_ATOMIC_COUNTER_BARRIER_BIT);
2840                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2841                 glMemoryBarrier(GL_ATOMIC_COUNTER_BARRIER_BIT);
2842                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2843                 glMemoryBarrier(GL_ATOMIC_COUNTER_BARRIER_BIT);
2844                 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2845
2846                 // validate
2847                 UVec4 data[s * s];
2848                 glReadBuffer(GL_COLOR_ATTACHMENT0);
2849                 glReadPixels(0, 0, s, s, GL_RGBA_INTEGER, GL_UNSIGNED_INT, data);
2850                 if (!CheckCounterValues(s * s, data, s * s * 3))
2851                         return ERROR;
2852
2853                 glReadBuffer(GL_COLOR_ATTACHMENT1);
2854                 glReadPixels(0, 0, s, s, GL_RGBA_INTEGER, GL_UNSIGNED_INT, data);
2855                 if (!CheckCounterValues(s * s, data, 0))
2856                         return ERROR;
2857
2858                 if (!CheckFinalCounterValue(counter_buffer_, 0, 256))
2859                         return ERROR;
2860                 if (!CheckFinalCounterValue(counter_buffer_, 4, 0))
2861                         return ERROR;
2862
2863                 return NO_ERROR;
2864         }
2865
2866         virtual long Cleanup()
2867         {
2868                 glDeleteFramebuffers(1, &fbo_);
2869                 glDeleteTextures(2, rt_);
2870                 glViewport(0, 0, getWindowWidth(), getWindowHeight());
2871                 glDeleteBuffers(1, &counter_buffer_);
2872                 glDeleteVertexArrays(1, &vao_);
2873                 glDeleteBuffers(1, &vbo_);
2874                 glDeleteProgram(prog_);
2875                 glUseProgram(0);
2876                 return NO_ERROR;
2877         }
2878 };
2879
2880 class NegativeSSBO : public BasicUsageCS
2881 {
2882         virtual std::string Title()
2883         {
2884                 return NL "GLSL errors";
2885         }
2886         virtual std::string Purpose()
2887         {
2888                 return NL "Verify that atomic counters cannot be declared in the buffer block.";
2889         }
2890         virtual std::string Method()
2891         {
2892                 return NL "";
2893         }
2894         virtual std::string PassCriteria()
2895         {
2896                 return NL "";
2897         }
2898
2899         GLuint prog_;
2900
2901         virtual long Setup()
2902         {
2903                 prog_ = 0;
2904                 return NO_ERROR;
2905         }
2906         virtual long Run()
2907         {
2908
2909                 const char* const glsl_cs =
2910                         NL "layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;" NL
2911                            "layout(binding = 0, offset = 0) uniform atomic_uint ac_counter_dec;" NL
2912                            "layout(std430) buffer Output {" NL "  mediump uint data_inc[256];" NL "  mediump uint data_dec[256];" NL
2913                            "  layout(binding = 0, offset = 16) uniform atomic_uint ac_counter0;" NL "} g_out;" NL "void main() {" NL
2914                            "  mediump uint offset = 32u * gl_GlobalInvocationID.y + gl_GlobalInvocationID.x;" NL
2915                            "  g_out.data_inc[offset] = atomicCounterIncrement(ac_counter0);" NL
2916                            "  g_out.data_dec[offset] = atomicCounterDecrement(ac_counter_dec);" NL "}";
2917
2918                 prog_ = CreateComputeProgram(glsl_cs);
2919                 glLinkProgram(prog_);
2920                 if (CheckProgram(prog_))
2921                 {
2922                         Output("Link should fail because atomic counters cannot be declared in the buffer block.\n");
2923                         return ERROR;
2924                 }
2925                 return NO_ERROR;
2926         }
2927         virtual long Cleanup()
2928         {
2929                 glDeleteProgram(prog_);
2930                 return NO_ERROR;
2931         }
2932 };
2933
2934 class NegativeUBO : public BasicUsageCS
2935 {
2936         virtual std::string Title()
2937         {
2938                 return NL "GLSL errors";
2939         }
2940         virtual std::string Purpose()
2941         {
2942                 return NL "Verify that atomic counters cannot be declared in uniform block.";
2943         }
2944         virtual std::string Method()
2945         {
2946                 return NL "";
2947         }
2948         virtual std::string PassCriteria()
2949         {
2950                 return NL "";
2951         }
2952
2953         GLuint prog_;
2954
2955         virtual long Setup()
2956         {
2957                 prog_ = 0;
2958                 return NO_ERROR;
2959         }
2960
2961         virtual long Run()
2962         {
2963                 const char* const glsl_cs =
2964                         NL "layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;" NL "uniform Block {" NL
2965                            "  uniform atomic_uint ac_counter;" NL "};" NL "layout(std430) buffer Output {" NL
2966                            "  mediump uint data_inc[256];" NL "} g_out;" NL "void main() {" NL
2967                            "  mediump uint offset = 32u * gl_GlobalInvocationID.y + gl_GlobalInvocationID.x;" NL
2968                            "  g_out.data_inc[offset] = atomicCounterIncrement(ac_counter);" NL "}";
2969
2970                 prog_ = CreateComputeProgram(glsl_cs);
2971                 glLinkProgram(prog_);
2972                 if (CheckProgram(prog_))
2973                 {
2974                         Output("Link should fail because atomic counters cannot be declared in the uniform block.\n");
2975                         return ERROR;
2976                 }
2977                 return NO_ERROR;
2978         }
2979
2980         virtual long Cleanup()
2981         {
2982                 glDeleteProgram(prog_);
2983                 return NO_ERROR;
2984         }
2985 };
2986
2987 class BasicUsageNoOffset : public BasicUsageCS
2988 {
2989         virtual std::string Title()
2990         {
2991                 return NL "Atomic Counters usage in the Compute Shader stage";
2992         }
2993         virtual std::string Purpose()
2994         {
2995                 return NL "Verify that atomic counters work as expected in the Compute Shader stage when decalred with no "
2996                                   "offset qualifier." NL "In particular make sure that values returned by GLSL built-in functions" NL
2997                                   "atomicCounterIncrement and atomicCounterDecrement are unique in every shader invocation." NL
2998                                   "Also make sure that the final values in atomic counter buffer objects are as expected.";
2999         }
3000         virtual std::string Method()
3001         {
3002                 return NL "";
3003         }
3004         virtual std::string PassCriteria()
3005         {
3006                 return NL "";
3007         }
3008
3009         GLuint counter_buffer_;
3010         GLuint prog_;
3011         GLuint m_buffer;
3012
3013         virtual long Setup()
3014         {
3015                 counter_buffer_ = 0;
3016                 prog_                   = 0;
3017                 m_buffer                = 0;
3018                 return NO_ERROR;
3019         }
3020
3021         virtual long Run()
3022         {
3023                 // create program
3024                 const char* const glsl_cs =
3025                         NL "layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;" NL
3026                            "layout(binding = 0) uniform atomic_uint ac_counter_inc;" NL
3027                            "layout(binding = 0) uniform atomic_uint ac_counter_dec;" NL "layout(std430) buffer Output {" NL
3028                            "  mediump uint data_inc[256];" NL "  mediump uint data_dec[256];" NL "} g_out;" NL "void main() {" NL
3029                            "  mediump uint offset = 32u * gl_GlobalInvocationID.y + gl_GlobalInvocationID.x;" NL
3030                            "  g_out.data_inc[offset] = atomicCounterIncrement(ac_counter_inc);" NL
3031                            "  g_out.data_dec[offset] = atomicCounterDecrement(ac_counter_dec);" NL "}";
3032                 prog_ = CreateComputeProgram(glsl_cs);
3033                 glLinkProgram(prog_);
3034                 if (!CheckProgram(prog_))
3035                         return ERROR;
3036
3037                 // create atomic counter buffer
3038                 glGenBuffers(1, &counter_buffer_);
3039                 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, counter_buffer_);
3040                 glBufferData(GL_ATOMIC_COUNTER_BUFFER, 8, NULL, GL_DYNAMIC_COPY);
3041                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
3042
3043                 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, counter_buffer_);
3044                 unsigned int* ptr = static_cast<unsigned int*>(
3045                         glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, 8, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT));
3046                 *ptr++ = 0;
3047                 *ptr++ = 256;
3048                 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
3049
3050                 glGenBuffers(1, &m_buffer);
3051                 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
3052                 glBufferData(GL_SHADER_STORAGE_BUFFER, 512 * sizeof(GLuint), NULL, GL_DYNAMIC_DRAW);
3053                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
3054
3055                 glUseProgram(prog_);
3056                 glDispatchCompute(4, 1, 1);
3057
3058                 long    error = NO_ERROR;
3059                 GLuint* data;
3060                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer);
3061                 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3062                 data =
3063                         static_cast<GLuint*>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 512 * sizeof(GLuint), GL_MAP_READ_BIT));
3064
3065                 std::sort(data, data + 512);
3066                 for (int i = 0; i < 512; i += 2)
3067                 {
3068                         if (data[i] != data[i + 1])
3069                         {
3070                                 Output("Pair of values should be equal, got: %d, %d\n", data[i], data[i + 1]);
3071                                 error = ERROR;
3072                         }
3073                         if (i < 510 && data[i] == data[i + 2])
3074                         {
3075                                 Output("Too many same values found: %d, index: %d\n", data[i], i);
3076                                 error = ERROR;
3077                         }
3078                 }
3079
3080                 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3081                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
3082                 return error;
3083         }
3084
3085         virtual long Cleanup()
3086         {
3087                 glDeleteBuffers(1, &counter_buffer_);
3088                 glDeleteBuffers(1, &m_buffer);
3089                 glDeleteProgram(prog_);
3090                 glUseProgram(0);
3091                 return NO_ERROR;
3092         }
3093 };
3094
3095 class NegativeUniform : public SACSubcaseBase
3096 {
3097         virtual std::string Title()
3098         {
3099                 return NL "GLSL errors";
3100         }
3101         virtual std::string Purpose()
3102         {
3103                 return NL "Verify that atomicCounterIncrement/atomicCounterDecrement "
3104                                   "cannot be used on normal uniform.";
3105         }
3106         virtual std::string Method()
3107         {
3108                 return NL "";
3109         }
3110         virtual std::string PassCriteria()
3111         {
3112                 return NL "";
3113         }
3114
3115         GLuint prog_;
3116
3117         virtual long Setup()
3118         {
3119                 prog_ = 0;
3120                 return NO_ERROR;
3121         }
3122         virtual long Run()
3123         {
3124
3125                 GLint p1, p2;
3126                 glGetIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS, &p1);
3127                 glGetIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTERS, &p2);
3128                 if (p1 < 1 || p2 < 1)
3129                 {
3130                         OutputNotSupported(
3131                                 "GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS or GL_MAX_FRAGMENT_ATOMIC_COUNTERS are less than required");
3132                         return NOT_SUPPORTED;
3133                 }
3134
3135                 // create program
3136                 const char* glsl_vs = "#version 310 es" NL "layout(location = 0) in vec4 i_vertex;" NL "void main() {" NL
3137                                                           "  gl_Position = i_vertex;" NL "}";
3138
3139                 const char* glsl_fs1 =
3140                         "#version 310 es" NL "layout(location = 0) out uvec4 o_color[4];" NL "uniform uint ac_counter0;" NL
3141                         "void main() {" NL "  o_color[0] = uvec4(atomicCounterIncrement(ac_counter0));" NL "}";
3142
3143                 prog_ = glCreateProgram();
3144
3145                 GLuint sh = glCreateShader(GL_VERTEX_SHADER);
3146                 glAttachShader(prog_, sh);
3147                 glShaderSource(sh, 1, &glsl_vs, NULL);
3148                 glCompileShader(sh);
3149                 GLint status_comp;
3150                 glGetShaderiv(sh, GL_COMPILE_STATUS, &status_comp);
3151                 if (status_comp != GL_TRUE)
3152                 {
3153                         Output("Unexpected error during vertex shader compilation.");
3154                         return ERROR;
3155                 }
3156                 glDeleteShader(sh);
3157
3158                 sh = glCreateShader(GL_FRAGMENT_SHADER);
3159                 glAttachShader(prog_, sh);
3160                 glShaderSource(sh, 1, &glsl_fs1, NULL);
3161                 glCompileShader(sh);
3162                 glGetShaderiv(sh, GL_COMPILE_STATUS, &status_comp);
3163                 glDeleteShader(sh);
3164
3165                 GLint status;
3166                 glLinkProgram(prog_);
3167                 glGetProgramiv(prog_, GL_LINK_STATUS, &status);
3168                 if (status_comp == GL_TRUE && status == GL_TRUE)
3169                 {
3170                         Output("Expected error during fragment shader compilation or linking.");
3171                         return ERROR;
3172                 }
3173                 return NO_ERROR;
3174         }
3175         virtual long Cleanup()
3176         {
3177                 glDeleteProgram(prog_);
3178                 return NO_ERROR;
3179         }
3180 };
3181
3182 class NegativeArray : public BasicUsageCS
3183 {
3184         virtual std::string Title()
3185         {
3186                 return NL "GLSL errors";
3187         }
3188         virtual std::string Purpose()
3189         {
3190                 return NL "Verify that atomicCounterIncrement/atomicCounterDecrement "
3191                                   "cannot be used on array of atomic counters.";
3192         }
3193         virtual std::string Method()
3194         {
3195                 return NL "";
3196         }
3197         virtual std::string PassCriteria()
3198         {
3199                 return NL "";
3200         }
3201
3202         GLuint prog_;
3203
3204         virtual long Setup()
3205         {
3206                 prog_ = 0;
3207                 return NO_ERROR;
3208         }
3209         virtual long Run()
3210         {
3211
3212                 const char* const glsl_cs =
3213                         NL "layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;" NL
3214                            "layout(binding = 0) uniform atomic_uint ac_counter[3];" NL "layout(std430) buffer Output {" NL
3215                            "  mediump uint data_inc[256];" NL "} g_out;" NL "void main() {" NL
3216                            "  mediump uint offset = 32u * gl_GlobalInvocationID.y + gl_GlobalInvocationID.x;" NL
3217                            "  g_out.data_inc[offset] = atomicCounterIncrement(ac_counter);" NL "}";
3218
3219                 prog_ = CreateComputeProgram(glsl_cs);
3220                 glLinkProgram(prog_);
3221                 if (CheckProgram(prog_))
3222                 {
3223                         Output("Link should fail because atomicCounterIncrement cannot be used on array of atomic counters.\n");
3224                         return ERROR;
3225                 }
3226                 return NO_ERROR;
3227         }
3228         virtual long Cleanup()
3229         {
3230                 glDeleteProgram(prog_);
3231                 return NO_ERROR;
3232         }
3233 };
3234
3235 class NegativeArithmetic : public BasicUsageCS
3236 {
3237         virtual std::string Title()
3238         {
3239                 return NL "GLSL errors";
3240         }
3241         virtual std::string Purpose()
3242         {
3243                 return NL "Verify that standard arithmetic operations \n"
3244                                   "cannot be performed on atomic counters.";
3245         }
3246         virtual std::string Method()
3247         {
3248                 return NL "";
3249         }
3250         virtual std::string PassCriteria()
3251         {
3252                 return NL "";
3253         }
3254
3255         GLuint prog_;
3256
3257         virtual long Setup()
3258         {
3259                 prog_ = 0;
3260                 return NO_ERROR;
3261         }
3262         virtual long Run()
3263         {
3264
3265                 const char* const glsl_cs =
3266                         NL "layout(local_size_x = 8, local_size_y = 8, local_size_z = 1) in;" NL
3267                            "layout(binding = 0) uniform atomic_uint ac_counter;" NL "layout(std430) buffer Output {" NL
3268                            "  mediump uint data_inc[256];" NL "} g_out;" NL "void main() {" NL
3269                            "  mediump uint offset = 32u * gl_GlobalInvocationID.y + gl_GlobalInvocationID.x;" NL
3270                            "  g_out.data_inc[offset] = ac_counter + 1;" NL "}";
3271
3272                 prog_ = CreateComputeProgram(glsl_cs);
3273                 glLinkProgram(prog_);
3274                 if (CheckProgram(prog_))
3275                 {
3276                         Output(
3277                                 "Link should fail because atomic counters cannot be incremented by standard arithmetic operations.\n");
3278                         return ERROR;
3279                 }
3280                 return NO_ERROR;
3281         }
3282
3283         virtual long Cleanup()
3284         {
3285                 glDeleteProgram(prog_);
3286                 return NO_ERROR;
3287         }
3288 };
3289
3290 class AdvancedManyDrawCalls2 : public SACSubcaseBase
3291 {
3292
3293         GLuint m_acbo, m_ssbo;
3294         GLuint m_vao;
3295         GLuint m_ppo, m_vsp, m_fsp;
3296
3297         virtual long Setup()
3298         {
3299                 glGenBuffers(1, &m_acbo);
3300                 glGenBuffers(1, &m_ssbo);
3301                 glGenVertexArrays(1, &m_vao);
3302                 glGenProgramPipelines(1, &m_ppo);
3303                 m_vsp = m_fsp = 0;
3304                 return NO_ERROR;
3305         }
3306
3307         virtual long Cleanup()
3308         {
3309                 glDeleteBuffers(1, &m_acbo);
3310                 glDeleteBuffers(1, &m_ssbo);
3311                 glDeleteVertexArrays(1, &m_vao);
3312                 glDeleteProgramPipelines(1, &m_ppo);
3313                 glDeleteProgram(m_vsp);
3314                 glDeleteProgram(m_fsp);
3315                 return NO_ERROR;
3316         }
3317
3318         virtual long Run()
3319         {
3320
3321                 GLint p1, p2;
3322                 glGetIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS, &p1);
3323                 glGetIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTERS, &p2);
3324                 if (p1 < 1 || p2 < 1)
3325                 {
3326                         OutputNotSupported(
3327                                 "GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS or GL_MAX_FRAGMENT_ATOMIC_COUNTERS are less than required");
3328                         return NOT_SUPPORTED;
3329                 }
3330
3331                 const char* const glsl_vs = "#version 310 es" NL "void main() {" NL "#ifdef GL_ES" NL
3332                                                                         "  gl_PointSize = 1.0f;" NL "#endif" NL "  gl_Position = vec4(0, 0, 0, 1);" NL "}";
3333                 const char* const glsl_fs =
3334                         "#version 310 es" NL "layout(binding = 0) uniform atomic_uint g_counter;" NL
3335                         "layout(std430, binding = 0) buffer Output {" NL "  uint g_output[];" NL "};" NL "void main() {" NL
3336                         "  uint c = atomicCounterIncrement(g_counter);" NL "  g_output[c] = c;" NL "}";
3337
3338                 m_vsp = glCreateShaderProgramv(GL_VERTEX_SHADER, 1, &glsl_vs);
3339                 m_fsp = glCreateShaderProgramv(GL_FRAGMENT_SHADER, 1, &glsl_fs);
3340                 if (!CheckProgram(m_vsp) || !CheckProgram(m_fsp))
3341                         return ERROR;
3342
3343                 glUseProgramStages(m_ppo, GL_VERTEX_SHADER_BIT, m_vsp);
3344                 glUseProgramStages(m_ppo, GL_FRAGMENT_SHADER_BIT, m_fsp);
3345
3346                 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, m_acbo);
3347                 {
3348                         GLuint data = 0;
3349                         glBufferData(GL_ATOMIC_COUNTER_BUFFER, 4, &data, GL_DYNAMIC_COPY);
3350                 }
3351
3352                 {
3353                         std::vector<GLuint> data(1000, 0xffff);
3354                         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_ssbo);
3355                         glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)(data.size() * 4), &data[0], GL_DYNAMIC_READ);
3356                 }
3357
3358                 // draw
3359                 glViewport(0, 0, 1, 1);
3360                 glBindProgramPipeline(m_ppo);
3361                 glBindVertexArray(m_vao);
3362                 for (int i = 0; i < 100; ++i)
3363                 {
3364                         glDrawArrays(GL_POINTS, 0, 1);
3365                 }
3366
3367                 glViewport(0, 0, getWindowWidth(), getWindowHeight());
3368
3369                 long status = NO_ERROR;
3370
3371                 {
3372                         GLuint* data;
3373
3374                         glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_acbo);
3375                         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3376                         data = static_cast<GLuint*>(glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, 4, GL_MAP_READ_BIT));
3377                         if (data[0] != 100)
3378                         {
3379                                 status = ERROR;
3380                                 Output("AC buffer content is %u, sholud be 100.\n", data[0]);
3381                         }
3382                         glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
3383                         glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
3384
3385                         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_ssbo);
3386                         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3387                         data = static_cast<GLuint*>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 100 * 4, GL_MAP_READ_BIT));
3388                         std::sort(data, data + 100);
3389                         for (GLuint i = 0; i < 100; ++i)
3390                         {
3391                                 if (data[i] != i)
3392                                 {
3393                                         status = ERROR;
3394                                         Output("data[%u] is %u, should be %u.\n", i, data[i], i);
3395                                 }
3396                         }
3397                         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3398                         glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
3399                 }
3400
3401                 return status;
3402         }
3403 };
3404
3405 class AdvancedUsageMultipleComputeDispatches : public SACSubcaseBase
3406 {
3407         GLuint m_acbo, m_ssbo;
3408         GLuint m_ppo, m_csp;
3409
3410         virtual long Setup()
3411         {
3412                 glGenBuffers(1, &m_acbo);
3413                 glGenBuffers(1, &m_ssbo);
3414                 glGenProgramPipelines(1, &m_ppo);
3415                 m_csp = 0;
3416                 return NO_ERROR;
3417         }
3418
3419         virtual long Cleanup()
3420         {
3421                 glDeleteBuffers(1, &m_acbo);
3422                 glDeleteBuffers(1, &m_ssbo);
3423                 glDeleteProgramPipelines(1, &m_ppo);
3424                 glDeleteProgram(m_csp);
3425                 return NO_ERROR;
3426         }
3427
3428         virtual long Run()
3429         {
3430                 // create program
3431                 const char* const glsl_cs =
3432                         "#version 310 es" NL "layout(local_size_x = 1) in;" NL
3433                         "layout(binding = 0) uniform atomic_uint g_counter;" NL "layout(std430, binding = 0) buffer Output {" NL
3434                         "  mediump uint g_output[];" NL "};" NL "void main() {" NL
3435                         "  mediump uint c = atomicCounterIncrement(g_counter);" NL "  g_output[c] = c;" NL "}";
3436
3437                 m_csp = glCreateShaderProgramv(GL_COMPUTE_SHADER, 1, &glsl_cs);
3438                 if (!CheckProgram(m_csp))
3439                         return ERROR;
3440                 glUseProgramStages(m_ppo, GL_COMPUTE_SHADER_BIT, m_csp);
3441
3442                 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, m_acbo);
3443                 {
3444                         GLuint data = 0;
3445                         glBufferData(GL_ATOMIC_COUNTER_BUFFER, 4, &data, GL_DYNAMIC_COPY);
3446                 }
3447
3448                 {
3449                         std::vector<GLuint> data(1000, 0xffff);
3450                         glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_ssbo);
3451                         glBufferData(GL_SHADER_STORAGE_BUFFER, (GLsizeiptr)(data.size() * 4), &data[0], GL_DYNAMIC_READ);
3452                 }
3453
3454                 glBindProgramPipeline(m_ppo);
3455                 for (int i = 0; i < 100; ++i)
3456                 {
3457                         glDispatchCompute(1, 1, 1);
3458                 }
3459
3460                 long status = NO_ERROR;
3461
3462                 {
3463                         GLuint* data;
3464
3465                         glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_acbo);
3466                         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3467                         data = static_cast<GLuint*>(glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, 4, GL_MAP_READ_BIT));
3468                         if (data[0] != 100)
3469                         {
3470                                 status = ERROR;
3471                                 Output("AC buffer content is %u, sholud be 100.\n", data[0]);
3472                         }
3473                         glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
3474                         glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
3475
3476                         glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_ssbo);
3477                         glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3478                         data = static_cast<GLuint*>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, 100 * 4, GL_MAP_READ_BIT));
3479                         std::sort(data, data + 100);
3480                         for (GLuint i = 0; i < 100; ++i)
3481                         {
3482                                 if (data[i] != i)
3483                                 {
3484                                         status = ERROR;
3485                                         Output("data[%u] is %u, should be %u.\n", i, data[i], i);
3486                                 }
3487                         }
3488                         glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3489                         glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
3490                 }
3491
3492                 return status;
3493         }
3494 };
3495
3496 class BasicGLSLBuiltIn : public BasicUsageCS
3497 {
3498 public:
3499         virtual std::string Title()
3500         {
3501                 return NL "gl_Max* Check";
3502         }
3503         virtual std::string Purpose()
3504         {
3505                 return NL "Verify that gl_Max*Counters and gl_Max*Bindings exist in glsl and their values are no lower" NL
3506                                   "than minimum required by the spec and are no different from their GL_MAX_* counterparts.";
3507         }
3508
3509         GLuint prog_;
3510         GLuint m_buffer;
3511
3512         virtual long Setup()
3513         {
3514                 prog_   = 0;
3515                 m_buffer = 0;
3516                 return NO_ERROR;
3517         }
3518
3519         virtual long Run()
3520         {
3521                 // create program
3522                 const char* const glsl_cs = NL
3523                         "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;" NL "layout(std430) buffer Output {" NL
3524                         "  mediump uint data;" NL "} g_out;" NL "uniform mediump int m_vac;" NL "uniform mediump int m_fac;" NL
3525                         "uniform mediump int m_csac;" NL "uniform mediump int m_cac;" NL "uniform mediump int m_abuf;" NL
3526                         "void main() {" NL "  mediump uint res = 1u;" NL
3527                         "  if (gl_MaxVertexAtomicCounters < 0 || gl_MaxVertexAtomicCounters != m_vac)" NL "     res = res * 2u;" NL
3528                         "  if (gl_MaxFragmentAtomicCounters < 0 || gl_MaxFragmentAtomicCounters != m_fac)" NL
3529                         "     res = res * 3u;" NL
3530                         "  if (gl_MaxComputeAtomicCounters < 8 || gl_MaxComputeAtomicCounters != m_csac)" NL
3531                         "     res = res * 5u;" NL
3532                         "  if (gl_MaxCombinedAtomicCounters < 8 || gl_MaxCombinedAtomicCounters != m_cac)" NL
3533                         "     res = res * 7u;" NL
3534                         "  if (gl_MaxAtomicCounterBindings < 1 || gl_MaxAtomicCounterBindings != m_abuf)" NL
3535                         "     res = res * 11u;" NL "  g_out.data = res;" NL "}";
3536
3537                 prog_ = CreateComputeProgram(glsl_cs);
3538                 glLinkProgram(prog_);
3539                 if (!CheckProgram(prog_))
3540                         return ERROR;
3541                 glUseProgram(prog_);
3542
3543                 int m_vac;
3544                 int m_fac;
3545                 int m_csac;
3546                 int m_cac;
3547                 int m_abuf;
3548                 glGetIntegerv(GL_MAX_VERTEX_ATOMIC_COUNTERS, &m_vac);
3549                 glUniform1i(glGetUniformLocation(prog_, "m_vac"), m_vac);
3550                 glGetIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTERS, &m_fac);
3551                 glUniform1i(glGetUniformLocation(prog_, "m_fac"), m_fac);
3552                 glGetIntegerv(GL_MAX_COMPUTE_ATOMIC_COUNTERS, &m_csac);
3553                 glUniform1i(glGetUniformLocation(prog_, "m_csac"), m_csac);
3554                 glGetIntegerv(GL_MAX_COMBINED_ATOMIC_COUNTERS, &m_cac);
3555                 glUniform1i(glGetUniformLocation(prog_, "m_cac"), m_cac);
3556                 glGetIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, &m_abuf);
3557                 glUniform1i(glGetUniformLocation(prog_, "m_abuf"), m_abuf);
3558
3559                 glGenBuffers(1, &m_buffer);
3560                 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_buffer);
3561                 glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(GLuint), NULL, GL_DYNAMIC_DRAW);
3562                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
3563
3564                 glDispatchCompute(1, 1, 1);
3565
3566                 long    error = NO_ERROR;
3567                 GLuint* data;
3568                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, m_buffer);
3569                 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
3570                 data = static_cast<GLuint*>(glMapBufferRange(GL_SHADER_STORAGE_BUFFER, 0, sizeof(GLuint), GL_MAP_READ_BIT));
3571                 if (data[0] != 1u)
3572                 {
3573                         Output("Expected 1, got: %d", data[0]);
3574                         error = ERROR;
3575                 }
3576                 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3577                 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
3578
3579                 return error;
3580         }
3581
3582         virtual long Cleanup()
3583         {
3584                 glDeleteBuffers(1, &m_buffer);
3585                 glDeleteProgram(prog_);
3586                 glUseProgram(0);
3587                 return NO_ERROR;
3588         }
3589 };
3590
3591 ShaderAtomicCountersTests::ShaderAtomicCountersTests(glcts::Context& context)
3592         : TestCaseGroup(context, "shader_atomic_counters", "")
3593 {
3594 }
3595
3596 ShaderAtomicCountersTests::~ShaderAtomicCountersTests(void)
3597 {
3598 }
3599
3600 void ShaderAtomicCountersTests::init()
3601 {
3602         using namespace glcts;
3603         setOutput(m_context.getTestContext().getLog());
3604         addChild(new TestSubcase(m_context, "basic-buffer-operations", TestSubcase::Create<BasicBufferOperations>));
3605         addChild(new TestSubcase(m_context, "basic-buffer-state", TestSubcase::Create<BasicBufferState>));
3606         addChild(new TestSubcase(m_context, "basic-buffer-bind", TestSubcase::Create<BasicBufferBind>));
3607         addChild(new TestSubcase(m_context, "basic-program-max", TestSubcase::Create<BasicProgramMax>));
3608         addChild(new TestSubcase(m_context, "basic-program-query", TestSubcase::Create<BasicProgramQuery>));
3609         addChild(new TestSubcase(m_context, "basic-usage-simple", TestSubcase::Create<BasicUsageSimple>));
3610         addChild(new TestSubcase(m_context, "basic-usage-no-offset", TestSubcase::Create<BasicUsageNoOffset>));
3611         addChild(new TestSubcase(m_context, "basic-usage-fs", TestSubcase::Create<BasicUsageFS>));
3612         addChild(new TestSubcase(m_context, "basic-usage-vs", TestSubcase::Create<BasicUsageVS>));
3613         addChild(new TestSubcase(m_context, "basic-usage-cs", TestSubcase::Create<BasicUsageCS>));
3614         addChild(new TestSubcase(m_context, "basic-glsl-built-in", TestSubcase::Create<BasicGLSLBuiltIn>));
3615         addChild(new TestSubcase(m_context, "advanced-usage-multi-stage", TestSubcase::Create<AdvancedUsageMultiStage>));
3616         addChild(new TestSubcase(m_context, "advanced-usage-draw-update-draw",
3617                                                          TestSubcase::Create<AdvancedUsageDrawUpdateDraw>));
3618         addChild(
3619                 new TestSubcase(m_context, "advanced-usage-many-counters", TestSubcase::Create<AdvancedUsageManyCounters>));
3620         addChild(
3621                 new TestSubcase(m_context, "advanced-usage-switch-programs", TestSubcase::Create<AdvancedUsageSwitchPrograms>));
3622         addChild(new TestSubcase(m_context, "advanced-usage-ubo", TestSubcase::Create<AdvancedUsageUBO>));
3623         addChild(new TestSubcase(m_context, "advanced-usage-many-draw-calls", TestSubcase::Create<AdvancedManyDrawCalls>));
3624         addChild(
3625                 new TestSubcase(m_context, "advanced-usage-many-draw-calls2", TestSubcase::Create<AdvancedManyDrawCalls2>));
3626         addChild(new TestSubcase(m_context, "advanced-usage-many-dispatches",
3627                                                          TestSubcase::Create<AdvancedUsageMultipleComputeDispatches>));
3628         addChild(new TestSubcase(m_context, "negative-api", TestSubcase::Create<NegativeAPI>));
3629         addChild(new TestSubcase(m_context, "negative-glsl", TestSubcase::Create<NegativeGLSL>));
3630         addChild(new TestSubcase(m_context, "negative-ssbo", TestSubcase::Create<NegativeSSBO>));
3631         addChild(new TestSubcase(m_context, "negative-ubo", TestSubcase::Create<NegativeUBO>));
3632         addChild(new TestSubcase(m_context, "negative-uniform", TestSubcase::Create<NegativeUniform>));
3633         addChild(new TestSubcase(m_context, "negative-array", TestSubcase::Create<NegativeArray>));
3634         addChild(new TestSubcase(m_context, "negative-arithmetic", TestSubcase::Create<NegativeArithmetic>));
3635 }
3636 }