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:
Title()49 virtual std::string Title()
50 {
51 return NL "";
52 }
Purpose()53 virtual std::string Purpose()
54 {
55 return NL "";
56 }
Method()57 virtual std::string Method()
58 {
59 return NL "";
60 }
PassCriteria()61 virtual std::string PassCriteria()
62 {
63 return NL "";
64 }
65
~SACSubcaseBase()66 virtual ~SACSubcaseBase()
67 {
68 }
69
CheckProgram(GLuint program)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
getWindowWidth()85 int getWindowWidth()
86 {
87 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
88 return renderTarget.getWidth();
89 }
90
getWindowHeight()91 int getWindowHeight()
92 {
93 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
94 return renderTarget.getHeight();
95 }
96
ValidateReadBuffer(const Vec4 & expected)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
LinkProgram(GLuint program)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
CreateProgram(const char * src_vs,const char * src_fs,bool link)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
CreateShaderProgram(GLenum type,GLsizei count,const GLchar ** strings)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
CreateQuad(GLuint * vao,GLuint * vbo,GLuint * ebo)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
CreateTriangle(GLuint * vao,GLuint * vbo,GLuint * ebo)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
GLenumToString(GLenum e)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
CheckMaxValue(GLenum e,GLint expected)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
CheckGetCommands(GLenum e,GLint expected)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
CheckBufferBindingState(GLuint index,GLint binding,GLint64 start,GLint64 size)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
CheckUniform(GLuint prog,const GLchar * uniform_name,GLuint uniform_index,GLint uniform_type,GLint uniform_size,GLint uniform_offset,GLint uniform_array_stride)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, ¶m);
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, ¶m);
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, ¶m);
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, ¶m);
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, ¶m);
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, ¶m);
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, ¶m);
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, ¶m);
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
CheckCounterValues(GLuint size,GLuint * values,GLuint min_value)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
CheckCounterValues(GLuint size,UVec4 * data,GLuint min_value)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
CheckFinalCounterValue(GLuint buffer,GLintptr offset,GLuint expected_value)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:
Buffer()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 }
~Buffer()646 ~Buffer()
647 {
648 glDeleteBuffers(1, &name_);
649 }
name() const650 GLuint name() const
651 {
652 return name_;
653 }
Verify()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<deUintptr>(static_cast<int*>(ptr))
726 << " should be " << reinterpret_cast<deUintptr>(static_cast<int*>(map_pointer_)) << tcu::TestLog::EndMessage;
727 return ERROR;
728 }
729 return NO_ERROR;
730 }
Data(GLsizeiptr size,const void * data,GLenum usage)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 }
MapRange(GLintptr offset,GLsizeiptr length,GLbitfield access)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 }
Unmap()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:
Title()788 virtual std::string Title()
789 {
790 return NL "Atomic Counters usage in the Compute Shader stage";
791 }
Purpose()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 }
Method()799 virtual std::string Method()
800 {
801 return NL "";
802 }
PassCriteria()803 virtual std::string PassCriteria()
804 {
805 return NL "";
806 }
807
808 GLuint counter_buffer_;
809 GLuint prog_;
810 GLuint m_buffer;
811
Setup()812 virtual long Setup()
813 {
814 counter_buffer_ = 0;
815 prog_ = 0;
816 m_buffer = 0;
817 return NO_ERROR;
818 }
819
CreateComputeProgram(const std::string & cs)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
CheckProgram(GLuint program,bool * compile_error=NULL)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
Run()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
Cleanup()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 {
Title()1019 virtual std::string Title()
1020 {
1021 return NL "Atomic Counter Buffer - basic operations";
1022 }
Purpose()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 }
Method()1030 virtual std::string Method()
1031 {
1032 return NL "";
1033 }
PassCriteria()1034 virtual std::string PassCriteria()
1035 {
1036 return NL "";
1037 }
1038
1039 GLuint buffer_;
1040
Setup()1041 virtual long Setup()
1042 {
1043 buffer_ = 0;
1044 return NO_ERROR;
1045 }
Run()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 }
Cleanup()1137 virtual long Cleanup()
1138 {
1139 glDeleteBuffers(1, &buffer_);
1140 return NO_ERROR;
1141 }
1142 };
1143
1144 class BasicBufferState : public SACSubcaseBase
1145 {
Title()1146 virtual std::string Title()
1147 {
1148 return NL "Atomic Counter Buffer - state";
1149 }
Purpose()1150 virtual std::string Purpose()
1151 {
1152 return NL "Verify that setting and getting buffer state works as expected for new buffer target.";
1153 }
Method()1154 virtual std::string Method()
1155 {
1156 return NL "";
1157 }
PassCriteria()1158 virtual std::string PassCriteria()
1159 {
1160 return NL "";
1161 }
1162
Run()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 {
Title()1188 virtual std::string Title()
1189 {
1190 return NL "Atomic Counter Buffer - binding";
1191 }
Purpose()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 }
Method()1199 virtual std::string Method()
1200 {
1201 return NL "";
1202 }
PassCriteria()1203 virtual std::string PassCriteria()
1204 {
1205 return NL "";
1206 }
1207
1208 GLuint buffer_;
1209
Setup()1210 virtual long Setup()
1211 {
1212 buffer_ = 0;
1213 return NO_ERROR;
1214 }
Run()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 }
Cleanup()1301 virtual long Cleanup()
1302 {
1303 glDeleteBuffers(1, &buffer_);
1304 return NO_ERROR;
1305 }
1306 };
1307
1308 class BasicProgramMax : public SACSubcaseBase
1309 {
Title()1310 virtual std::string Title()
1311 {
1312 return NL "Program - max values";
1313 }
Purpose()1314 virtual std::string Purpose()
1315 {
1316 return NL "Verify all max values which deal with atomic counter buffers.";
1317 }
Method()1318 virtual std::string Method()
1319 {
1320 return NL "";
1321 }
PassCriteria()1322 virtual std::string PassCriteria()
1323 {
1324 return NL "";
1325 }
1326
Run()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 {
Title()1355 virtual std::string Title()
1356 {
1357 return NL "Program - atomic counters queries";
1358 }
Purpose()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 }
Method()1365 virtual std::string Method()
1366 {
1367 return NL "";
1368 }
PassCriteria()1369 virtual std::string PassCriteria()
1370 {
1371 return NL "";
1372 }
1373
1374 GLuint counter_buffer_, m_buffer;
1375 GLuint prog_;
1376
Setup()1377 virtual long Setup()
1378 {
1379 counter_buffer_ = 0;
1380 m_buffer = 0;
1381 prog_ = 0;
1382 return NO_ERROR;
1383 }
1384
Run()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
Cleanup()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 {
Title()1506 virtual std::string Title()
1507 {
1508 return NL "Simple Use Case";
1509 }
Purpose()1510 virtual std::string Purpose()
1511 {
1512 return NL "Verify that simple usage of atomic counters work as expected.";
1513 }
Method()1514 virtual std::string Method()
1515 {
1516 return NL "";
1517 }
PassCriteria()1518 virtual std::string PassCriteria()
1519 {
1520 return NL "";
1521 }
1522
1523 GLuint counter_buffer_;
1524 GLuint storage_buffer_;
1525 GLuint prog_;
1526
Setup()1527 virtual long Setup()
1528 {
1529 counter_buffer_ = 0;
1530 storage_buffer_ = 0;
1531 prog_ = 0;
1532 return NO_ERROR;
1533 }
1534
Run()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
Cleanup()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 {
Title()1594 virtual std::string Title()
1595 {
1596 return NL "Atomic Counters usage in the Fragment Shader stage";
1597 }
Purpose()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 }
Method()1605 virtual std::string Method()
1606 {
1607 return NL "";
1608 }
PassCriteria()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
Setup()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 }
Run()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 }
Cleanup()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 {
Title()1733 virtual std::string Title()
1734 {
1735 return NL "Atomic Counters usage in the Vertex Shader stage";
1736 }
Purpose()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 }
Method()1744 virtual std::string Method()
1745 {
1746 return NL "";
1747 }
PassCriteria()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
Setup()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 }
Run()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 }
Cleanup()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 {
Title()1898 virtual std::string Title()
1899 {
1900 return NL "Same atomic counter accessed from multiple shader stages";
1901 }
Purpose()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 }
Method()1908 virtual std::string Method()
1909 {
1910 return NL "";
1911 }
PassCriteria()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
Setup()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 }
Run()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 }
Cleanup()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 {
Title()2070 virtual std::string Title()
2071 {
2072 return NL "Update via Draw Call and update via MapBufferRange";
2073 }
Purpose()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 }
Method()2083 virtual std::string Method()
2084 {
2085 return NL "";
2086 }
PassCriteria()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
Setup()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 }
Run()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 }
Cleanup()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 {
Title()2246 virtual std::string Title()
2247 {
2248 return NL "Large atomic counters array indexed with uniforms";
2249 }
Purpose()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 }
Method()2256 virtual std::string Method()
2257 {
2258 return NL "";
2259 }
PassCriteria()2260 virtual std::string PassCriteria()
2261 {
2262 return NL "";
2263 }
2264
2265 GLuint counter_buffer_, m_ssbo;
2266 GLuint prog_;
2267
Setup()2268 virtual long Setup()
2269 {
2270 counter_buffer_ = 0;
2271 m_ssbo = 0;
2272 prog_ = 0;
2273 return NO_ERROR;
2274 }
2275
Run()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
Cleanup()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 {
Title()2423 virtual std::string Title()
2424 {
2425 return NL "Switching several program objects with different atomic counters with different bindings";
2426 }
Purpose()2427 virtual std::string Purpose()
2428 {
2429 return NL "Verify that each program upadate atomic counter buffer object in appropriate binding point.";
2430 }
Method()2431 virtual std::string Method()
2432 {
2433 return NL "";
2434 }
PassCriteria()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
GenVSSrc(int binding,int offset)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 }
GenFSSrc(int binding,int offset)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 }
Setup()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 }
Run()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 }
Cleanup()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 {
Title()2578 virtual std::string Title()
2579 {
2580 return NL "Atomic Counters used to access Uniform Buffer Objects";
2581 }
Purpose()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 }
Method()2588 virtual std::string Method()
2589 {
2590 return NL "";
2591 }
PassCriteria()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
Setup()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
Run()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
Cleanup()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 {
Title()2686 virtual std::string Title()
2687 {
2688 return NL "NegativeAPI";
2689 }
Purpose()2690 virtual std::string Purpose()
2691 {
2692 return NL "Verify errors reported by BindBuffer* commands.";
2693 }
Method()2694 virtual std::string Method()
2695 {
2696 return NL "";
2697 }
PassCriteria()2698 virtual std::string PassCriteria()
2699 {
2700 return NL "";
2701 }
2702
2703 GLuint buffer;
2704
Setup()2705 virtual long Setup()
2706 {
2707 return NO_ERROR;
2708 }
Run()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 }
Cleanup()2745 virtual long Cleanup()
2746 {
2747 glDeleteBuffers(1, &buffer);
2748 return NO_ERROR;
2749 }
2750 };
2751
2752 class NegativeGLSL : public BasicUsageCS
2753 {
Title()2754 virtual std::string Title()
2755 {
2756 return NL "GLSL errors";
2757 }
Purpose()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 }
Method()2762 virtual std::string Method()
2763 {
2764 return NL "";
2765 }
PassCriteria()2766 virtual std::string PassCriteria()
2767 {
2768 return NL "";
2769 }
2770
2771 GLuint prog_;
2772
Setup()2773 virtual long Setup()
2774 {
2775 prog_ = 0;
2776 return NO_ERROR;
2777 }
2778
Run()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 }
Cleanup()2802 virtual long Cleanup()
2803 {
2804 glDeleteProgram(prog_);
2805 return NO_ERROR;
2806 }
2807 };
2808
2809 class AdvancedManyDrawCalls : public SACSubcaseBase
2810 {
Title()2811 virtual std::string Title()
2812 {
2813 return NL "Atomic Counters usage in multiple draw calls";
2814 }
Purpose()2815 virtual std::string Purpose()
2816 {
2817 return NL "Verify atomic counters behaviour across multiple draw calls.";
2818 }
Method()2819 virtual std::string Method()
2820 {
2821 return NL "";
2822 }
PassCriteria()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
Setup()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 }
Run()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
Cleanup()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 {
Title()2954 virtual std::string Title()
2955 {
2956 return NL "GLSL errors";
2957 }
Purpose()2958 virtual std::string Purpose()
2959 {
2960 return NL "Verify that atomic counters cannot be declared in the buffer block.";
2961 }
Method()2962 virtual std::string Method()
2963 {
2964 return NL "";
2965 }
PassCriteria()2966 virtual std::string PassCriteria()
2967 {
2968 return NL "";
2969 }
2970
2971 GLuint prog_;
2972
Setup()2973 virtual long Setup()
2974 {
2975 prog_ = 0;
2976 return NO_ERROR;
2977 }
Run()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 }
Cleanup()3002 virtual long Cleanup()
3003 {
3004 glDeleteProgram(prog_);
3005 return NO_ERROR;
3006 }
3007 };
3008
3009 class NegativeUBO : public BasicUsageCS
3010 {
Title()3011 virtual std::string Title()
3012 {
3013 return NL "GLSL errors";
3014 }
Purpose()3015 virtual std::string Purpose()
3016 {
3017 return NL "Verify that atomic counters cannot be declared in uniform block.";
3018 }
Method()3019 virtual std::string Method()
3020 {
3021 return NL "";
3022 }
PassCriteria()3023 virtual std::string PassCriteria()
3024 {
3025 return NL "";
3026 }
3027
3028 GLuint prog_;
3029
Setup()3030 virtual long Setup()
3031 {
3032 prog_ = 0;
3033 return NO_ERROR;
3034 }
3035
Run()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
Cleanup()3058 virtual long Cleanup()
3059 {
3060 glDeleteProgram(prog_);
3061 return NO_ERROR;
3062 }
3063 };
3064
3065 class BasicUsageNoOffset : public BasicUsageCS
3066 {
Title()3067 virtual std::string Title()
3068 {
3069 return NL "Atomic Counters usage in the Compute Shader stage";
3070 }
Purpose()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 }
Method()3078 virtual std::string Method()
3079 {
3080 return NL "";
3081 }
PassCriteria()3082 virtual std::string PassCriteria()
3083 {
3084 return NL "";
3085 }
3086
3087 GLuint counter_buffer_;
3088 GLuint prog_;
3089 GLuint m_buffer;
3090
Setup()3091 virtual long Setup()
3092 {
3093 counter_buffer_ = 0;
3094 prog_ = 0;
3095 m_buffer = 0;
3096 return NO_ERROR;
3097 }
3098
Run()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
Cleanup()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 {
Title()3179 virtual std::string Title()
3180 {
3181 return NL "GLSL errors";
3182 }
Purpose()3183 virtual std::string Purpose()
3184 {
3185 return NL "Verify that atomicCounterIncrement/atomicCounterDecrement "
3186 "cannot be used on normal uniform.";
3187 }
Method()3188 virtual std::string Method()
3189 {
3190 return NL "";
3191 }
PassCriteria()3192 virtual std::string PassCriteria()
3193 {
3194 return NL "";
3195 }
3196
3197 GLuint prog_;
3198
Setup()3199 virtual long Setup()
3200 {
3201 prog_ = 0;
3202 return NO_ERROR;
3203 }
Run()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 }
Cleanup()3261 virtual long Cleanup()
3262 {
3263 glDeleteProgram(prog_);
3264 return NO_ERROR;
3265 }
3266 };
3267
3268 class NegativeArray : public BasicUsageCS
3269 {
Title()3270 virtual std::string Title()
3271 {
3272 return NL "GLSL errors";
3273 }
Purpose()3274 virtual std::string Purpose()
3275 {
3276 return NL "Verify that atomicCounterIncrement/atomicCounterDecrement "
3277 "cannot be used on array of atomic counters.";
3278 }
Method()3279 virtual std::string Method()
3280 {
3281 return NL "";
3282 }
PassCriteria()3283 virtual std::string PassCriteria()
3284 {
3285 return NL "";
3286 }
3287
3288 GLuint prog_;
3289
Setup()3290 virtual long Setup()
3291 {
3292 prog_ = 0;
3293 return NO_ERROR;
3294 }
Run()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 }
Cleanup()3317 virtual long Cleanup()
3318 {
3319 glDeleteProgram(prog_);
3320 return NO_ERROR;
3321 }
3322 };
3323
3324 class NegativeArithmetic : public BasicUsageCS
3325 {
Title()3326 virtual std::string Title()
3327 {
3328 return NL "GLSL errors";
3329 }
Purpose()3330 virtual std::string Purpose()
3331 {
3332 return NL "Verify that standard arithmetic operations \n"
3333 "cannot be performed on atomic counters.";
3334 }
Method()3335 virtual std::string Method()
3336 {
3337 return NL "";
3338 }
PassCriteria()3339 virtual std::string PassCriteria()
3340 {
3341 return NL "";
3342 }
3343
3344 GLuint prog_;
3345
Setup()3346 virtual long Setup()
3347 {
3348 prog_ = 0;
3349 return NO_ERROR;
3350 }
Run()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
Cleanup()3374 virtual long Cleanup()
3375 {
3376 glDeleteProgram(prog_);
3377 return NO_ERROR;
3378 }
3379 };
3380
3381 class NegativeUnsizedArray : public SACSubcaseBase
3382 {
Title()3383 virtual std::string Title()
3384 {
3385 return NL "GLSL errors";
3386 }
3387
Purpose()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
Method()3393 virtual std::string Method()
3394 {
3395 return NL "";
3396 }
3397
PassCriteria()3398 virtual std::string PassCriteria()
3399 {
3400 return NL "";
3401 }
3402
Run()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
Setup()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
Cleanup()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
Run()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
Setup()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
Cleanup()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
Run()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:
Title()3643 virtual std::string Title()
3644 {
3645 return NL "gl_Max* Check";
3646 }
Purpose()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
Setup()3656 virtual long Setup()
3657 {
3658 prog_ = 0;
3659 m_buffer = 0;
3660 return NO_ERROR;
3661 }
3662
Run()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
Cleanup()3727 virtual long Cleanup()
3728 {
3729 glDeleteBuffers(1, &m_buffer);
3730 glDeleteProgram(prog_);
3731 glUseProgram(0);
3732 return NO_ERROR;
3733 }
3734 };
3735
ShaderAtomicCountersTests(glcts::Context & context)3736 ShaderAtomicCountersTests::ShaderAtomicCountersTests(glcts::Context& context)
3737 : TestCaseGroup(context, "shader_atomic_counters", "")
3738 {
3739 }
3740
~ShaderAtomicCountersTests(void)3741 ShaderAtomicCountersTests::~ShaderAtomicCountersTests(void)
3742 {
3743 }
3744
init()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 }
3782