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