1 /*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
5 * Copyright (c) 2014-2016 The Khronos Group Inc.
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
22 */ /*-------------------------------------------------------------------*/
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"
46 class SACSubcaseBase : public glcts::SubcaseBase
49 virtual std::string Title()
53 virtual std::string Purpose()
57 virtual std::string Method()
61 virtual std::string PassCriteria()
66 virtual ~SACSubcaseBase()
70 bool CheckProgram(GLuint program)
73 glGetProgramiv(program, GL_LINK_STATUS, &status);
75 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
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;
82 return status == GL_TRUE;
87 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
88 return renderTarget.getWidth();
93 const tcu::RenderTarget& renderTarget = m_context.getRenderContext().getRenderTarget();
94 return renderTarget.getHeight();
97 long ValidateReadBuffer(const Vec4& expected)
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);
105 glu::readPixels(m_context.getRenderContext(), 0, 0, renderedFrame.getAccess());
107 for (int y = 0; y < viewportH; ++y)
109 for (int x = 0; x < viewportW; ++x)
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)));
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);
122 void LinkProgram(GLuint program)
124 glLinkProgram(program);
127 glGetProgramInfoLog(program, sizeof(log), &length, log);
130 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
131 << log << tcu::TestLog::EndMessage;
135 GLuint CreateProgram(const char* src_vs, const char* src_fs, bool link)
137 const GLuint p = glCreateProgram();
141 GLuint sh = glCreateShader(GL_VERTEX_SHADER);
142 glAttachShader(p, sh);
144 glShaderSource(sh, 1, &src_vs, NULL);
149 GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
150 glAttachShader(p, sh);
152 glShaderSource(sh, 1, &src_fs, NULL);
162 GLuint CreateShaderProgram(GLenum type, GLsizei count, const GLchar** strings)
164 GLuint program = glCreateShaderProgramv(type, count, strings);
165 GLint status = GL_TRUE;
166 glGetProgramiv(program, GL_LINK_STATUS, &status);
167 if (status == GL_FALSE)
171 glGetProgramInfoLog(program, sizeof(log), &length, log);
174 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program Info Log:\n"
175 << log << tcu::TestLog::EndMessage;
181 void CreateQuad(GLuint* vao, GLuint* vbo, GLuint* ebo)
185 // interleaved data (vertex, color0 (green), color1 (blue), color2 (red))
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,
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);
198 std::vector<GLushort> index_data(4);
199 for (int i = 0; i < 4; ++i)
201 index_data[i] = static_cast<GLushort>(i);
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);
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);
223 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *ebo);
225 glBindVertexArray(0);
228 void CreateTriangle(GLuint* vao, GLuint* vbo, GLuint* ebo)
232 // interleaved data (vertex, color0 (green), color1 (blue), color2 (red))
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,
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);
244 std::vector<GLushort> index_data(3);
245 for (int i = 0; i < 3; ++i)
247 index_data[i] = static_cast<GLushort>(i);
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);
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);
269 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, *ebo);
271 glBindVertexArray(0);
274 const char* GLenumToString(GLenum e)
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";
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";
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";
310 bool CheckMaxValue(GLenum e, GLint expected)
315 glGetIntegerv(e, &i);
316 m_context.getTestContext().getLog()
317 << tcu::TestLog::Message << GLenumToString(e) << " = " << i << tcu::TestLog::EndMessage;
322 m_context.getTestContext().getLog()
323 << tcu::TestLog::Message << GLenumToString(e) << " state is incorrect (GetIntegerv, is: " << i
324 << ", expected: " << expected << ")" << tcu::TestLog::EndMessage;
328 glGetInteger64v(e, &i64);
329 if (i64 < static_cast<GLint64>(expected))
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;
339 if (f < static_cast<GLfloat>(expected))
342 m_context.getTestContext().getLog()
343 << tcu::TestLog::Message << GLenumToString(e) << " state is incorrect (GetFloatv, is: " << f
344 << ", expected: " << expected << ")" << tcu::TestLog::EndMessage;
348 glGetBooleanv(e, &b);
353 bool CheckGetCommands(GLenum e, GLint expected)
358 glGetIntegerv(e, &i);
362 m_context.getTestContext().getLog()
363 << tcu::TestLog::Message << GLenumToString(e) << " state is incorrect (GetIntegerv, is: " << i
364 << ", expected: " << expected << ")" << tcu::TestLog::EndMessage;
368 glGetInteger64v(e, &i64);
369 if (i64 != static_cast<GLint64>(expected))
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;
379 if (f != static_cast<GLfloat>(expected))
382 m_context.getTestContext().getLog()
383 << tcu::TestLog::Message << GLenumToString(e) << " state is incorrect (GetFloatv, is: " << f
384 << ", expected: " << expected << ")" << tcu::TestLog::EndMessage;
388 glGetBooleanv(e, &b);
389 if (b != (expected ? GL_TRUE : GL_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;
400 bool CheckBufferBindingState(GLuint index, GLint binding, GLint64 start, GLint64 size)
405 glGetIntegeri_v(GL_ATOMIC_COUNTER_BUFFER_BINDING, index, &i);
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;
416 glGetInteger64i_v(GL_ATOMIC_COUNTER_BUFFER_BINDING, index, &i64);
417 if (i64 != static_cast<GLint64>(binding))
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;
426 glGetInteger64i_v(GL_ATOMIC_COUNTER_BUFFER_START, index, &i64);
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;
435 glGetInteger64i_v(GL_ATOMIC_COUNTER_BUFFER_SIZE, index, &i64);
436 if (i64 != size && i64 != 0)
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;
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)
455 glGetUniformIndices(prog, 1, &uniform_name, &index);
456 if (index != uniform_index)
458 m_context.getTestContext().getLog()
459 << tcu::TestLog::Message << "Uniform: " << uniform_name
460 << ": Bad index returned by glGetUniformIndices." << tcu::TestLog::EndMessage;
464 const GLsizei uniform_length = static_cast<GLsizei>(strlen(uniform_name));
471 glGetProgramResourceName(prog, GL_UNIFORM, uniform_index, sizeof(name), &length, name);
472 if (length != uniform_length)
474 m_context.getTestContext().getLog()
475 << tcu::TestLog::Message << "Uniform: " << uniform_name << ": Length is " << length << " should be "
476 << uniform_length << tcu::TestLog::EndMessage;
479 glGetActiveUniform(prog, uniform_index, sizeof(name), &length, &size, &type, name);
480 if (strcmp(name, uniform_name))
482 m_context.getTestContext().getLog()
483 << tcu::TestLog::Message << "Uniform: " << uniform_name << ": Bad name returned by glGetActiveUniform."
484 << tcu::TestLog::EndMessage;
487 if (length != uniform_length)
489 m_context.getTestContext().getLog()
490 << tcu::TestLog::Message << "Uniform: " << uniform_name << ": Length is " << length << " should be "
491 << uniform_length << tcu::TestLog::EndMessage;
494 if (size != uniform_size)
496 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Uniform: " << uniform_name << ": Size is "
497 << size << " should be " << uniform_size << tcu::TestLog::EndMessage;
500 if (type != static_cast<GLenum>(uniform_type))
502 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Uniform: " << uniform_name << ": Type is "
503 << type << " should be " << uniform_type << tcu::TestLog::EndMessage;
508 glGetActiveUniformsiv(prog, 1, &uniform_index, GL_UNIFORM_TYPE, ¶m);
509 if (param != uniform_type)
511 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Uniform: " << uniform_name << ": Type is "
512 << param << " should be " << uniform_type << tcu::TestLog::EndMessage;
515 glGetActiveUniformsiv(prog, 1, &uniform_index, GL_UNIFORM_SIZE, ¶m);
516 if (param != uniform_size)
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;
523 glGetActiveUniformsiv(prog, 1, &uniform_index, GL_UNIFORM_NAME_LENGTH, ¶m);
524 if (param != (uniform_length + 1))
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;
531 glGetActiveUniformsiv(prog, 1, &uniform_index, GL_UNIFORM_BLOCK_INDEX, ¶m);
534 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Uniform: " << uniform_name
535 << ": GL_UNIFORM_BLOCK_INDEX should be -1." << tcu::TestLog::EndMessage;
538 glGetActiveUniformsiv(prog, 1, &uniform_index, GL_UNIFORM_OFFSET, ¶m);
539 if (param != uniform_offset)
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;
546 glGetActiveUniformsiv(prog, 1, &uniform_index, GL_UNIFORM_ARRAY_STRIDE, ¶m);
547 if (param != uniform_array_stride)
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;
554 glGetActiveUniformsiv(prog, 1, &uniform_index, GL_UNIFORM_MATRIX_STRIDE, ¶m);
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;
562 glGetActiveUniformsiv(prog, 1, &uniform_index, GL_UNIFORM_IS_ROW_MAJOR, ¶m);
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;
574 bool CheckCounterValues(GLuint size, GLuint* values, GLuint min_value)
576 std::sort(values, values + size);
577 for (GLuint i = 0; i < size; ++i)
579 m_context.getTestContext().getLog() << tcu::TestLog::Message << values[i] << tcu::TestLog::EndMessage;
580 if (values[i] != i + min_value)
582 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Counter value is " << values[i]
583 << " should be " << i + min_value << tcu::TestLog::EndMessage;
590 bool CheckCounterValues(GLuint size, UVec4* data, GLuint min_value)
592 std::vector<GLuint> values(size);
593 for (GLuint j = 0; j < size; ++j)
595 values[j] = data[j].x();
597 std::sort(values.begin(), values.end());
598 for (GLuint i = 0; i < size; ++i)
600 m_context.getTestContext().getLog() << tcu::TestLog::Message << values[i] << tcu::TestLog::EndMessage;
601 if (values[i] != i + min_value)
603 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Counter value is " << values[i]
604 << " should be " << i + min_value << tcu::TestLog::EndMessage;
611 bool CheckFinalCounterValue(GLuint buffer, GLintptr offset, GLuint expected_value)
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)
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);
623 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
624 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
629 class Buffer : public glcts::GLWrapper
634 , usage_(GL_STATIC_DRAW)
635 , access_(GL_WRITE_ONLY)
642 glGenBuffers(1, &name_);
643 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, name_);
644 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
648 glDeleteBuffers(1, &name_);
659 glGetBufferParameteri64v(GL_ATOMIC_COUNTER_BUFFER, GL_BUFFER_SIZE, &i64);
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;
667 glGetBufferParameteriv(GL_ATOMIC_COUNTER_BUFFER, GL_BUFFER_USAGE, &i);
668 if (i != static_cast<GLint>(usage_))
670 m_context.getTestContext().getLog() << tcu::TestLog::Message << "BUFFER_USAGE is " << i << " should be "
671 << usage_ << tcu::TestLog::EndMessage;
674 if (this->m_context.getContextInfo().isExtensionSupported("GL_OES_mapbuffer"))
676 glGetBufferParameteriv(GL_ATOMIC_COUNTER_BUFFER, GL_BUFFER_ACCESS, &i);
677 if (i != static_cast<GLint>(access_))
679 m_context.getTestContext().getLog() << tcu::TestLog::Message << "BUFFER_ACCESS is " << i
680 << " should be " << access_ << tcu::TestLog::EndMessage;
686 m_context.getTestContext().getLog()
687 << tcu::TestLog::Message << "GL_OES_mapbuffer not supported, skipping GL_BUFFER_ACCESS enum"
688 << tcu::TestLog::EndMessage;
690 glGetBufferParameteriv(GL_ATOMIC_COUNTER_BUFFER, GL_BUFFER_ACCESS_FLAGS, &i);
691 if (i != access_flags_)
693 m_context.getTestContext().getLog() << tcu::TestLog::Message << "BUFFER_ACCESS_FLAGS is " << i
694 << " should be " << access_flags_ << tcu::TestLog::EndMessage;
697 glGetBufferParameteriv(GL_ATOMIC_COUNTER_BUFFER, GL_BUFFER_MAPPED, &i);
700 m_context.getTestContext().getLog() << tcu::TestLog::Message << "BUFFER_MAPPED is " << i << " should be "
701 << mapped_ << tcu::TestLog::EndMessage;
704 glGetBufferParameteri64v(GL_ATOMIC_COUNTER_BUFFER, GL_BUFFER_MAP_OFFSET, &i64);
705 if (i64 != map_offset_)
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;
712 glGetBufferParameteri64v(GL_ATOMIC_COUNTER_BUFFER, GL_BUFFER_MAP_LENGTH, &i64);
713 if (i64 != map_length_)
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;
721 glGetBufferPointerv(GL_ATOMIC_COUNTER_BUFFER, GL_BUFFER_MAP_POINTER, &ptr);
722 if (ptr != map_pointer_)
724 m_context.getTestContext().getLog()
725 << tcu::TestLog::Message << "BUFFER_MAP_POINTER is " << reinterpret_cast<long>(static_cast<int*>(ptr))
726 << " should be " << reinterpret_cast<long>(static_cast<int*>(map_pointer_)) << tcu::TestLog::EndMessage;
731 void Data(GLsizeiptr size, const void* data, GLenum usage)
735 glBufferData(GL_ATOMIC_COUNTER_BUFFER, size, data, usage);
737 void* MapRange(GLintptr offset, GLsizeiptr length, GLbitfield access)
739 assert(mapped_ == GL_FALSE);
741 map_pointer_ = glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, offset, length, access);
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;
757 assert(mapped_ == GL_TRUE);
759 if (glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER))
765 access_ = GL_WRITE_ONLY;
785 class BasicUsageCS : public SACSubcaseBase
788 virtual std::string Title()
790 return NL "Atomic Counters usage in the Compute Shader stage";
792 virtual std::string Purpose()
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.";
799 virtual std::string Method()
803 virtual std::string PassCriteria()
808 GLuint counter_buffer_;
820 GLuint CreateComputeProgram(const std::string& cs)
822 const GLuint p = glCreateProgram();
824 const char* const kGLSLVer = "#version 310 es\n";
828 const GLuint sh = glCreateShader(GL_COMPUTE_SHADER);
829 glAttachShader(p, sh);
831 const char* const src[2] = { kGLSLVer, cs.c_str() };
832 glShaderSource(sh, 2, src, NULL);
839 bool CheckProgram(GLuint program, bool* compile_error = NULL)
841 GLint compile_status = GL_TRUE;
843 glGetProgramiv(program, GL_LINK_STATUS, &status);
845 if (status == GL_FALSE)
847 GLint attached_shaders;
848 glGetProgramiv(program, GL_ATTACHED_SHADERS, &attached_shaders);
850 if (attached_shaders > 0)
852 std::vector<GLuint> shaders(attached_shaders);
853 glGetAttachedShaders(program, attached_shaders, NULL, &shaders[0]);
855 for (GLint i = 0; i < attached_shaders; ++i)
858 glGetShaderiv(shaders[i], GL_SHADER_TYPE, reinterpret_cast<GLint*>(&type));
861 case GL_VERTEX_SHADER:
862 m_context.getTestContext().getLog()
863 << tcu::TestLog::Message << "*** Vertex Shader ***" << tcu::TestLog::EndMessage;
865 case GL_TESS_CONTROL_SHADER:
866 m_context.getTestContext().getLog()
867 << tcu::TestLog::Message << "*** Tessellation Control Shader ***"
868 << tcu::TestLog::EndMessage;
870 case GL_TESS_EVALUATION_SHADER:
871 m_context.getTestContext().getLog()
872 << tcu::TestLog::Message << "*** Tessellation Evaluation Shader ***"
873 << tcu::TestLog::EndMessage;
875 case GL_GEOMETRY_SHADER:
876 m_context.getTestContext().getLog()
877 << tcu::TestLog::Message << "*** Geometry Shader ***" << tcu::TestLog::EndMessage;
879 case GL_FRAGMENT_SHADER:
880 m_context.getTestContext().getLog()
881 << tcu::TestLog::Message << "*** Fragment Shader ***" << tcu::TestLog::EndMessage;
883 case GL_COMPUTE_SHADER:
884 m_context.getTestContext().getLog()
885 << tcu::TestLog::Message << "*** Compute Shader ***" << tcu::TestLog::EndMessage;
888 m_context.getTestContext().getLog()
889 << tcu::TestLog::Message << "*** Unknown Shader ***" << tcu::TestLog::EndMessage;
894 glGetShaderiv(shaders[i], GL_COMPILE_STATUS, &res);
896 compile_status = res;
900 glGetShaderiv(shaders[i], GL_SHADER_SOURCE_LENGTH, &length);
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;
910 glGetShaderiv(shaders[i], GL_INFO_LOG_LENGTH, &length);
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;
923 glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
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;
933 *compile_error = (compile_status == GL_TRUE ? false : true);
934 if (compile_status != GL_TRUE)
936 return status == GL_TRUE ? true : false;
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_))
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);
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));
966 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
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);
974 glDispatchCompute(4, 1, 1);
976 long error = NO_ERROR;
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));
983 std::sort(data, data + 512);
984 for (int i = 0; i < 512; i += 2)
986 if (data[i] != data[i + 1])
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;
993 if (i < 510 && data[i] == data[i + 2])
995 m_context.getTestContext().getLog()
996 << tcu::TestLog::Message << "Too many same values found: " << data[i] << ", index: " << i
997 << tcu::TestLog::EndMessage;
1002 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
1003 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
1007 virtual long Cleanup()
1009 glDeleteBuffers(1, &counter_buffer_);
1010 glDeleteBuffers(1, &m_buffer);
1011 glDeleteProgram(prog_);
1017 class BasicBufferOperations : public SACSubcaseBase
1019 virtual std::string Title()
1021 return NL "Atomic Counter Buffer - basic operations";
1023 virtual std::string Purpose()
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.";
1030 virtual std::string Method()
1034 virtual std::string PassCriteria()
1041 virtual long Setup()
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);
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));
1059 for (GLuint i = 0; i < 8; ++i)
1061 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
1062 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
1064 long res = NO_ERROR;
1066 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, buffer_);
1067 data = static_cast<GLuint*>(glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, 32, GL_MAP_READ_BIT));
1072 for (GLuint i = 0; i < 8; ++i)
1076 m_context.getTestContext().getLog() << tcu::TestLog::Message << "data[" << i << "] is: " << data[i]
1077 << " should be: " << i << tcu::TestLog::EndMessage;
1081 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
1082 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
1083 if (res != NO_ERROR)
1086 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, buffer_);
1087 ptr = static_cast<GLuint*>(glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, 32, GL_MAP_WRITE_BIT));
1092 for (GLuint i = 0; i < 8; ++i)
1094 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
1095 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
1097 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, buffer_);
1098 data = static_cast<GLuint*>(glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, 32, GL_MAP_READ_BIT));
1103 for (GLuint i = 0; i < 8; ++i)
1105 if (data[i] != i * 2)
1107 m_context.getTestContext().getLog() << tcu::TestLog::Message << "data[" << i << "] is: " << data[i]
1108 << " should be: " << i * 2 << tcu::TestLog::EndMessage;
1112 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
1113 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
1116 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, buffer_);
1117 for (GLuint i = 0; i < 8; ++i)
1119 glBufferSubData(GL_ATOMIC_COUNTER_BUFFER, 0, 32, data2);
1120 for (GLuint i = 0; i < 8; ++i)
1122 data = static_cast<GLuint*>(glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, 32, GL_MAP_READ_BIT));
1123 for (GLuint i = 0; i < 8; ++i)
1125 if (data[i] != i * 3)
1127 m_context.getTestContext().getLog() << tcu::TestLog::Message << "data[" << i << "] is: " << data[i]
1128 << " should be: " << i * 3 << tcu::TestLog::EndMessage;
1132 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
1133 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
1137 virtual long Cleanup()
1139 glDeleteBuffers(1, &buffer_);
1144 class BasicBufferState : public SACSubcaseBase
1146 virtual std::string Title()
1148 return NL "Atomic Counter Buffer - state";
1150 virtual std::string Purpose()
1152 return NL "Verify that setting and getting buffer state works as expected for new buffer target.";
1154 virtual std::string Method()
1158 virtual std::string PassCriteria()
1166 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, buffer.name());
1168 if (buffer.Verify() != NO_ERROR)
1171 buffer.Data(100, NULL, GL_DYNAMIC_COPY);
1172 if (buffer.Verify() != NO_ERROR)
1175 buffer.MapRange(10, 50, GL_MAP_WRITE_BIT);
1176 if (buffer.Verify() != NO_ERROR)
1179 if (buffer.Verify() != NO_ERROR)
1186 class BasicBufferBind : public SACSubcaseBase
1188 virtual std::string Title()
1190 return NL "Atomic Counter Buffer - binding";
1192 virtual std::string Purpose()
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.";
1199 virtual std::string Method()
1203 virtual std::string PassCriteria()
1210 virtual long Setup()
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;
1222 if (!CheckGetCommands(GL_ATOMIC_COUNTER_BUFFER_BINDING, 0))
1224 for (GLint index = 0; index < bindings; ++index)
1226 if (!CheckBufferBindingState(static_cast<GLuint>(index), 0, 0, 0))
1230 glGenBuffers(1, &buffer_);
1231 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, buffer_);
1233 if (!CheckGetCommands(GL_ATOMIC_COUNTER_BUFFER_BINDING, static_cast<GLint>(buffer_)))
1235 for (GLint index = 0; index < bindings; ++index)
1237 if (!CheckBufferBindingState(static_cast<GLuint>(index), 0, 0, 0))
1241 long res = NO_ERROR;
1243 glBufferData(GL_ATOMIC_COUNTER_BUFFER, 1000, NULL, GL_DYNAMIC_COPY);
1244 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
1246 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, buffer_);
1247 if (!CheckBufferBindingState(0, static_cast<GLint>(buffer_), 0, 1000))
1249 if (!CheckGetCommands(GL_ATOMIC_COUNTER_BUFFER_BINDING, static_cast<GLint>(buffer_)))
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))
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))
1259 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
1261 glBindBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, buffer_, 8, 32);
1262 if (!CheckBufferBindingState(0, static_cast<GLint>(buffer_), 8, 32))
1264 if (!CheckGetCommands(GL_ATOMIC_COUNTER_BUFFER_BINDING, static_cast<GLint>(buffer_)))
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))
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))
1275 glDeleteBuffers(1, &buffer_);
1279 glGetIntegerv(GL_ATOMIC_COUNTER_BUFFER_BINDING, &i);
1282 m_context.getTestContext().getLog()
1283 << tcu::TestLog::Message << "Generic binding point should be 0 after deleting bound buffer object."
1284 << tcu::TestLog::EndMessage;
1287 for (GLint index = 0; index < bindings; ++index)
1289 glGetIntegeri_v(GL_ATOMIC_COUNTER_BUFFER_BINDING, static_cast<GLuint>(index), &i);
1292 m_context.getTestContext().getLog()
1293 << tcu::TestLog::Message << "Binding point " << index
1294 << " should be 0 after deleting bound buffer object." << tcu::TestLog::EndMessage;
1301 virtual long Cleanup()
1303 glDeleteBuffers(1, &buffer_);
1308 class BasicProgramMax : public SACSubcaseBase
1310 virtual std::string Title()
1312 return NL "Program - max values";
1314 virtual std::string Purpose()
1316 return NL "Verify all max values which deal with atomic counter buffers.";
1318 virtual std::string Method()
1322 virtual std::string PassCriteria()
1329 if (!CheckMaxValue(GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, 1))
1331 if (!CheckMaxValue(GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE, 32))
1333 if (!CheckMaxValue(GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS, 1))
1335 if (!CheckMaxValue(GL_MAX_COMBINED_ATOMIC_COUNTERS, 8))
1337 if (!CheckMaxValue(GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS, 0))
1339 if (!CheckMaxValue(GL_MAX_VERTEX_ATOMIC_COUNTERS, 0))
1341 if (!CheckMaxValue(GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS, 1))
1343 if (!CheckMaxValue(GL_MAX_COMPUTE_ATOMIC_COUNTERS, 8))
1345 if (!CheckMaxValue(GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS, 0))
1347 if (!CheckMaxValue(GL_MAX_FRAGMENT_ATOMIC_COUNTERS, 0))
1353 class BasicProgramQuery : public BasicUsageCS
1355 virtual std::string Title()
1357 return NL "Program - atomic counters queries";
1359 virtual std::string Purpose()
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.";
1365 virtual std::string Method()
1369 virtual std::string PassCriteria()
1374 GLuint counter_buffer_, m_buffer;
1377 virtual long Setup()
1379 counter_buffer_ = 0;
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 "}";
1407 prog_ = CreateComputeProgram(glsl_cs);
1408 glLinkProgram(prog_);
1409 if (!CheckProgram(prog_))
1411 glUseProgram(prog_);
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)
1418 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_ACTIVE_ATOMIC_COUNTER_BUFFERS is "
1419 << active_buffers << " should be 1." << tcu::TestLog::EndMessage;
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)
1429 m_context.getTestContext().getLog() << tcu::TestLog::Message << "GL_ACTIVE_UNIFORMS is " << active_uniforms
1430 << " should be 8." << tcu::TestLog::EndMessage;
1433 for (GLuint index = 0; index < active_uniforms; ++index)
1436 glGetProgramResourceName(prog_, GL_UNIFORM, index, sizeof(name), NULL, name);
1437 uniforms_name_index.insert(std::make_pair(name, index));
1440 if (!CheckUniform(prog_, "ac_counter0", uniforms_name_index["ac_counter0"], GL_UNSIGNED_INT_ATOMIC_COUNTER, 1,
1443 if (!CheckUniform(prog_, "ac_counter1", uniforms_name_index["ac_counter1"], GL_UNSIGNED_INT_ATOMIC_COUNTER, 1,
1446 if (!CheckUniform(prog_, "ac_counter2", uniforms_name_index["ac_counter2"], GL_UNSIGNED_INT_ATOMIC_COUNTER, 1,
1449 if (!CheckUniform(prog_, "ac_counter3", uniforms_name_index["ac_counter3"], GL_UNSIGNED_INT_ATOMIC_COUNTER, 1,
1452 if (!CheckUniform(prog_, "ac_counter4", uniforms_name_index["ac_counter4"], GL_UNSIGNED_INT_ATOMIC_COUNTER, 1,
1455 if (!CheckUniform(prog_, "ac_counter5", uniforms_name_index["ac_counter5"], GL_UNSIGNED_INT_ATOMIC_COUNTER, 1,
1458 if (!CheckUniform(prog_, "ac_counter67[0]", uniforms_name_index["ac_counter67[0]"],
1459 GL_UNSIGNED_INT_ATOMIC_COUNTER, 2, 12, 4))
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);
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);
1474 glDispatchCompute(1, 1, 1);
1476 long error = NO_ERROR;
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)
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;
1488 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
1489 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
1494 virtual long Cleanup()
1496 glDeleteBuffers(1, &counter_buffer_);
1497 glDeleteBuffers(1, &m_buffer);
1498 glDeleteProgram(prog_);
1504 class BasicUsageSimple : public BasicUsageCS
1506 virtual std::string Title()
1508 return NL "Simple Use Case";
1510 virtual std::string Purpose()
1512 return NL "Verify that simple usage of atomic counters work as expected.";
1514 virtual std::string Method()
1518 virtual std::string PassCriteria()
1523 GLuint counter_buffer_;
1524 GLuint storage_buffer_;
1527 virtual long Setup()
1529 counter_buffer_ = 0;
1530 storage_buffer_ = 0;
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_))
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);
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));
1559 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
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);
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);
1572 if (glGetError() != GL_NO_ERROR)
1582 virtual long Cleanup()
1584 glDeleteBuffers(1, &counter_buffer_);
1585 glDeleteBuffers(1, &storage_buffer_);
1586 glDeleteProgram(prog_);
1592 class BasicUsageFS : public SACSubcaseBase
1594 virtual std::string Title()
1596 return NL "Atomic Counters usage in the Fragment Shader stage";
1598 virtual std::string Purpose()
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.";
1605 virtual std::string Method()
1609 virtual std::string PassCriteria()
1614 GLuint counter_buffer_;
1617 GLuint fbo_, rt_[2];
1619 virtual long Setup()
1621 counter_buffer_ = 0;
1624 fbo_ = rt_[0] = rt_[1] = 0;
1631 glGetIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS, &p1);
1632 glGetIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTERS, &p2);
1633 if (p1 < 1 || p2 < 2)
1636 "GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS or GL_MAX_FRAGMENT_ATOMIC_COUNTERS are less than required");
1637 return NOT_SUPPORTED;
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 "}";
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);
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);
1657 // create render targets
1659 glGenTextures(2, rt_);
1661 for (int i = 0; i < 2; ++i)
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);
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);
1680 CreateQuad(&vao_, &vbo_, NULL);
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));
1688 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
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);
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))
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))
1710 if (!CheckFinalCounterValue(counter_buffer_, 0, 64))
1712 if (!CheckFinalCounterValue(counter_buffer_, 4, 16))
1717 virtual long Cleanup()
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_);
1731 class BasicUsageVS : public SACSubcaseBase
1733 virtual std::string Title()
1735 return NL "Atomic Counters usage in the Vertex Shader stage";
1737 virtual std::string Purpose()
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.";
1744 virtual std::string Method()
1748 virtual std::string PassCriteria()
1753 GLuint counter_buffer_[2];
1754 GLuint xfb_buffer_[2];
1755 GLuint array_buffer_;
1759 virtual long Setup()
1761 counter_buffer_[0] = counter_buffer_[1] = 0;
1762 xfb_buffer_[0] = xfb_buffer_[1] = 0;
1772 glGetIntegerv(GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS, &p1);
1773 glGetIntegerv(GL_MAX_VERTEX_ATOMIC_COUNTERS, &p2);
1774 if (p1 < 2 || p2 < 2)
1777 "GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS or GL_MAX_VERTEX_ATOMIC_COUNTERS are less than required");
1778 return NOT_SUPPORTED;
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 "}";
1789 const char* src_fs = "#version 310 es \n"
1790 "out mediump vec4 color; \n"
1792 " color = vec4(0, 1, 0, 1); \n"
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);
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);
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);
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);
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));
1828 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
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));
1834 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
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);
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);
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))
1866 glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
1867 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
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))
1874 glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
1875 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
1877 if (!CheckFinalCounterValue(counter_buffer_[0], 0, 39))
1879 if (!CheckFinalCounterValue(counter_buffer_[1], 0, 45))
1884 virtual long Cleanup()
1886 glDeleteBuffers(2, counter_buffer_);
1887 glDeleteBuffers(2, xfb_buffer_);
1888 glDeleteBuffers(1, &array_buffer_);
1889 glDeleteVertexArrays(1, &vao_);
1890 glDeleteProgram(prog_);
1896 class AdvancedUsageMultiStage : public SACSubcaseBase
1898 virtual std::string Title()
1900 return NL "Same atomic counter accessed from multiple shader stages";
1902 virtual std::string Purpose()
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.";
1908 virtual std::string Method()
1912 virtual std::string PassCriteria()
1917 GLuint counter_buffer_;
1918 GLuint xfb_buffer_[2];
1921 GLuint fbo_, rt_[2];
1923 virtual long Setup()
1925 counter_buffer_ = 0;
1926 xfb_buffer_[0] = xfb_buffer_[1] = 0;
1929 fbo_ = rt_[0] = rt_[1] = 0;
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)
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;
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);
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],
1970 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
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);
1980 // create render targets
1982 glGenTextures(2, rt_);
1983 for (int i = 0; i < 2; ++i)
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);
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);
2002 CreateTriangle(&vao_, &vbo_, NULL);
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();
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]);
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))
2030 glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
2031 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
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))
2043 glUnmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
2044 glBindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
2046 if (!CheckFinalCounterValue(counter_buffer_, 32, 167))
2048 if (!CheckFinalCounterValue(counter_buffer_, 128, 33))
2053 virtual long Cleanup()
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_);
2068 class AdvancedUsageDrawUpdateDraw : public SACSubcaseBase
2070 virtual std::string Title()
2072 return NL "Update via Draw Call and update via MapBufferRange";
2074 virtual std::string Purpose()
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.";
2083 virtual std::string Method()
2087 virtual std::string PassCriteria()
2092 GLuint counter_buffer_;
2094 GLuint prog_, prog2_;
2095 GLuint fbo_, rt_[2];
2097 virtual long Setup()
2099 counter_buffer_ = 0;
2103 fbo_ = rt_[0] = rt_[1] = 0;
2110 glGetIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS, &p1);
2111 glGetIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTERS, &p2);
2112 if (p1 < 1 || p2 < 2)
2115 "GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS or GL_MAX_FRAGMENT_ATOMIC_COUNTERS are less than required");
2116 return NOT_SUPPORTED;
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);
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);
2139 // create render targets
2141 glGenTextures(2, rt_);
2143 for (int i = 0; i < 2; ++i)
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);
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);
2162 CreateQuad(&vao_, &vbo_, NULL);
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));
2170 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
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);
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));
2186 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
2189 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2190 glMemoryBarrier(GL_ATOMIC_COUNTER_BARRIER_BIT);
2193 glUseProgram(prog2_);
2194 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
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)
2202 if (data[i].x() != 896)
2204 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Counter value is " << data[i].x()
2205 << " should be 896." << tcu::TestLog::EndMessage;
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)
2214 if (data[i].x() != 1152)
2216 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Counter value is " << data[i].x()
2217 << " should be 896." << tcu::TestLog::EndMessage;
2222 if (!CheckFinalCounterValue(counter_buffer_, 0, 896))
2224 if (!CheckFinalCounterValue(counter_buffer_, 4, 1152))
2229 virtual long Cleanup()
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_);
2244 class AdvancedUsageManyCounters : public BasicUsageCS
2246 virtual std::string Title()
2248 return NL "Large atomic counters array indexed with uniforms";
2250 virtual std::string Purpose()
2252 return NL "Verify that large atomic counters array works as expected when indexed with dynamically uniform "
2254 "Built-ins tested: atomicCounterIncrement, atomicCounterDecrement and atomicCounter.";
2256 virtual std::string Method()
2260 virtual std::string PassCriteria()
2265 GLuint counter_buffer_, m_ssbo;
2268 virtual long Setup()
2270 counter_buffer_ = 0;
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 "}";
2295 prog_ = CreateComputeProgram(glsl_cs);
2296 glLinkProgram(prog_);
2297 if (!CheckProgram(prog_))
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);
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);
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);
2324 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, counter_buffer_);
2325 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, m_ssbo);
2326 glDispatchCompute(8, 8, 1);
2329 glMemoryBarrier(GL_ATOMIC_COUNTER_BARRIER_BIT | GL_SHADER_STORAGE_BARRIER_BIT);
2331 long error = NO_ERROR;
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))
2337 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2338 if (!CheckFinalCounterValue(counter_buffer_, 0, 1064))
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))
2346 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2347 if (!CheckFinalCounterValue(counter_buffer_, 1 * sizeof(GLuint), 1000 - 64))
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)
2356 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2357 if (!CheckFinalCounterValue(counter_buffer_, 2 * sizeof(GLuint), 1000))
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))
2365 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2366 if (!CheckFinalCounterValue(counter_buffer_, 3 * sizeof(GLuint), 1064))
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))
2374 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2375 if (!CheckFinalCounterValue(counter_buffer_, 4 * sizeof(GLuint), 1000 - 64))
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)
2384 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2385 if (!CheckFinalCounterValue(counter_buffer_, 5 * sizeof(GLuint), 1000))
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))
2393 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2394 if (!CheckFinalCounterValue(counter_buffer_, 6 * sizeof(GLuint), 1064))
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))
2402 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2403 if (!CheckFinalCounterValue(counter_buffer_, 7 * sizeof(GLuint), 1064))
2406 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
2407 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
2411 virtual long Cleanup()
2413 glDeleteBuffers(1, &counter_buffer_);
2414 glDeleteBuffers(1, &m_ssbo);
2415 glDeleteProgram(prog_);
2421 class AdvancedUsageSwitchPrograms : public SACSubcaseBase
2423 virtual std::string Title()
2425 return NL "Switching several program objects with different atomic counters with different bindings";
2427 virtual std::string Purpose()
2429 return NL "Verify that each program upadate atomic counter buffer object in appropriate binding point.";
2431 virtual std::string Method()
2435 virtual std::string PassCriteria()
2440 GLuint counter_buffer_[8];
2446 std::string GenVSSrc(int binding, int offset)
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
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 "}";
2456 std::string GenFSSrc(int binding, int offset)
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 "}";
2464 virtual long Setup()
2466 memset(counter_buffer_, 0, sizeof(counter_buffer_));
2469 memset(prog_, 0, sizeof(prog_));
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)
2483 OutputNotSupported("GL_MAX_*_ATOMIC_COUNTER_BUFFERS or GL_MAX_*_ATOMIC_COUNTERS are less than required");
2484 return NOT_SUPPORTED;
2488 for (int i = 0; i < 8; ++i)
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]);
2500 // create atomic counter buffers
2501 glGenBuffers(8, counter_buffer_);
2502 for (int i = 0; i < 8; ++i)
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],
2509 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
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);
2517 // create render target
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);
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);
2533 CreateTriangle(&vao_, &vbo_, NULL);
2536 for (GLuint i = 0; i < 8; ++i)
2538 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, i, counter_buffer_[i]);
2540 glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, xfb_buffer_);
2541 glBindFramebuffer(GL_FRAMEBUFFER, fbo_);
2542 glViewport(0, 0, s, s);
2543 glBindVertexArray(vao_);
2545 for (int i = 0; i < 8; ++i)
2547 glUseProgram(prog_[i]);
2548 glBeginTransformFeedback(GL_TRIANGLES);
2549 glDrawArrays(GL_TRIANGLES, 0, 3);
2550 glEndTransformFeedback();
2551 glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
2553 if (!CheckFinalCounterValue(counter_buffer_[i], i * 8, 3))
2555 if (!CheckFinalCounterValue(counter_buffer_[7 - i], 128 + i * 16, 64))
2560 virtual long Cleanup()
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]);
2576 class AdvancedUsageUBO : public BasicUsageCS
2578 virtual std::string Title()
2580 return NL "Atomic Counters used to access Uniform Buffer Objects";
2582 virtual std::string Purpose()
2584 return NL "Atomic counters are used to access UBOs. In that way each shader invocation can access UBO at "
2586 "This scenario is a base for some practical algorithms. Verify that it works as expected.";
2588 virtual std::string Method()
2592 virtual std::string PassCriteria()
2597 GLuint counter_buffer_, m_ssbo;
2598 GLuint uniform_buffer_;
2601 virtual long Setup()
2603 counter_buffer_ = 0;
2604 uniform_buffer_ = 0;
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_))
2624 glUniformBlockBinding(prog_, glGetUniformBlockIndex(prog_, "Data"), 1);
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);
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);
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);
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);
2656 long error = NO_ERROR;
2657 glMemoryBarrier(GL_UNIFORM_BARRIER_BIT | GL_SHADER_STORAGE_BARRIER_BIT | GL_ATOMIC_COUNTER_BARRIER_BIT);
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))
2663 if (!CheckFinalCounterValue(counter_buffer_, 0, 256))
2665 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
2667 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
2668 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
2673 virtual long Cleanup()
2675 glDeleteBuffers(1, &counter_buffer_);
2676 glDeleteBuffers(1, &uniform_buffer_);
2677 glDeleteBuffers(1, &m_ssbo);
2678 glDeleteProgram(prog_);
2684 class NegativeAPI : public SACSubcaseBase
2686 virtual std::string Title()
2688 return NL "NegativeAPI";
2690 virtual std::string Purpose()
2692 return NL "Verify errors reported by BindBuffer* commands.";
2694 virtual std::string Method()
2698 virtual std::string PassCriteria()
2705 virtual long Setup()
2711 long error = NO_ERROR;
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)
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;
2725 glBindBufferRange(GL_ATOMIC_COUNTER_BUFFER, res, buffer, 0, 4);
2726 if (glGetError() != GL_INVALID_VALUE)
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;
2734 glBindBufferRange(GL_ATOMIC_COUNTER_BUFFER, res - 1, buffer, 3, 4);
2735 if (glGetError() != GL_INVALID_VALUE)
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;
2745 virtual long Cleanup()
2747 glDeleteBuffers(1, &buffer);
2752 class NegativeGLSL : public BasicUsageCS
2754 virtual std::string Title()
2756 return NL "GLSL errors";
2758 virtual std::string Purpose()
2760 return NL "Verify that two different atomic counter uniforms with same binding cannot share same offset value.";
2762 virtual std::string Method()
2766 virtual std::string PassCriteria()
2773 virtual long Setup()
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 "}";
2790 prog_ = CreateComputeProgram(glsl_cs);
2791 glLinkProgram(prog_);
2792 if (CheckProgram(prog_))
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;
2802 virtual long Cleanup()
2804 glDeleteProgram(prog_);
2809 class AdvancedManyDrawCalls : public SACSubcaseBase
2811 virtual std::string Title()
2813 return NL "Atomic Counters usage in multiple draw calls";
2815 virtual std::string Purpose()
2817 return NL "Verify atomic counters behaviour across multiple draw calls.";
2819 virtual std::string Method()
2823 virtual std::string PassCriteria()
2828 GLuint counter_buffer_;
2831 GLuint fbo_, rt_[2];
2833 virtual long Setup()
2835 counter_buffer_ = 0;
2838 fbo_ = rt_[0] = rt_[1] = 0;
2845 glGetIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS, &p1);
2846 glGetIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTERS, &p2);
2847 if (p1 < 1 || p2 < 2)
2850 "GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS or GL_MAX_FRAGMENT_ATOMIC_COUNTERS are less than required");
2851 return NOT_SUPPORTED;
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);
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);
2870 // create render targets
2872 glGenTextures(2, rt_);
2874 for (int i = 0; i < 2; ++i)
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);
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);
2893 CreateQuad(&vao_, &vbo_, NULL);
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));
2901 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
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_);
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);
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))
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))
2930 if (!CheckFinalCounterValue(counter_buffer_, 0, 256))
2932 if (!CheckFinalCounterValue(counter_buffer_, 4, 0))
2938 virtual long Cleanup()
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_);
2952 class NegativeSSBO : public BasicUsageCS
2954 virtual std::string Title()
2956 return NL "GLSL errors";
2958 virtual std::string Purpose()
2960 return NL "Verify that atomic counters cannot be declared in the buffer block.";
2962 virtual std::string Method()
2966 virtual std::string PassCriteria()
2973 virtual long Setup()
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 "}";
2990 prog_ = CreateComputeProgram(glsl_cs);
2991 glLinkProgram(prog_);
2992 if (CheckProgram(prog_))
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;
3002 virtual long Cleanup()
3004 glDeleteProgram(prog_);
3009 class NegativeUBO : public BasicUsageCS
3011 virtual std::string Title()
3013 return NL "GLSL errors";
3015 virtual std::string Purpose()
3017 return NL "Verify that atomic counters cannot be declared in uniform block.";
3019 virtual std::string Method()
3023 virtual std::string PassCriteria()
3030 virtual long Setup()
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 "}";
3045 prog_ = CreateComputeProgram(glsl_cs);
3046 glLinkProgram(prog_);
3047 if (CheckProgram(prog_))
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;
3058 virtual long Cleanup()
3060 glDeleteProgram(prog_);
3065 class BasicUsageNoOffset : public BasicUsageCS
3067 virtual std::string Title()
3069 return NL "Atomic Counters usage in the Compute Shader stage";
3071 virtual std::string Purpose()
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.";
3078 virtual std::string Method()
3082 virtual std::string PassCriteria()
3087 GLuint counter_buffer_;
3091 virtual long Setup()
3093 counter_buffer_ = 0;
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_))
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);
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));
3126 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
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);
3133 glUseProgram(prog_);
3134 glDispatchCompute(4, 1, 1);
3136 long error = NO_ERROR;
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));
3143 std::sort(data, data + 512);
3144 for (int i = 0; i < 512; i += 2)
3146 if (data[i] != data[i + 1])
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;
3153 if (i < 510 && data[i] == data[i + 2])
3155 m_context.getTestContext().getLog()
3156 << tcu::TestLog::Message << "Too many same values found: " << data[i] << ", index: " << i
3157 << tcu::TestLog::EndMessage;
3162 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3163 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
3167 virtual long Cleanup()
3169 glDeleteBuffers(1, &counter_buffer_);
3170 glDeleteBuffers(1, &m_buffer);
3171 glDeleteProgram(prog_);
3177 class NegativeUniform : public SACSubcaseBase
3179 virtual std::string Title()
3181 return NL "GLSL errors";
3183 virtual std::string Purpose()
3185 return NL "Verify that atomicCounterIncrement/atomicCounterDecrement "
3186 "cannot be used on normal uniform.";
3188 virtual std::string Method()
3192 virtual std::string PassCriteria()
3199 virtual long Setup()
3208 glGetIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS, &p1);
3209 glGetIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTERS, &p2);
3210 if (p1 < 1 || p2 < 1)
3213 "GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS or GL_MAX_FRAGMENT_ATOMIC_COUNTERS are less than required");
3214 return NOT_SUPPORTED;
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 "}";
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 "}";
3225 prog_ = glCreateProgram();
3227 GLuint sh = glCreateShader(GL_VERTEX_SHADER);
3228 glAttachShader(prog_, sh);
3229 glShaderSource(sh, 1, &glsl_vs, NULL);
3230 glCompileShader(sh);
3232 glGetShaderiv(sh, GL_COMPILE_STATUS, &status_comp);
3233 if (status_comp != GL_TRUE)
3235 m_context.getTestContext().getLog()
3236 << tcu::TestLog::Message << "Unexpected error during vertex shader compilation."
3237 << tcu::TestLog::EndMessage;
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);
3250 glLinkProgram(prog_);
3251 glGetProgramiv(prog_, GL_LINK_STATUS, &status);
3252 if (status_comp == GL_TRUE && status == GL_TRUE)
3254 m_context.getTestContext().getLog()
3255 << tcu::TestLog::Message << "Expected error during fragment shader compilation or linking."
3256 << tcu::TestLog::EndMessage;
3261 virtual long Cleanup()
3263 glDeleteProgram(prog_);
3268 class NegativeArray : public BasicUsageCS
3270 virtual std::string Title()
3272 return NL "GLSL errors";
3274 virtual std::string Purpose()
3276 return NL "Verify that atomicCounterIncrement/atomicCounterDecrement "
3277 "cannot be used on array of atomic counters.";
3279 virtual std::string Method()
3283 virtual std::string PassCriteria()
3290 virtual long Setup()
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 "}";
3305 prog_ = CreateComputeProgram(glsl_cs);
3306 glLinkProgram(prog_);
3307 if (CheckProgram(prog_))
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;
3317 virtual long Cleanup()
3319 glDeleteProgram(prog_);
3324 class NegativeArithmetic : public BasicUsageCS
3326 virtual std::string Title()
3328 return NL "GLSL errors";
3330 virtual std::string Purpose()
3332 return NL "Verify that standard arithmetic operations \n"
3333 "cannot be performed on atomic counters.";
3335 virtual std::string Method()
3339 virtual std::string PassCriteria()
3346 virtual long Setup()
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 "}";
3361 prog_ = CreateComputeProgram(glsl_cs);
3362 glLinkProgram(prog_);
3363 if (CheckProgram(prog_))
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;
3374 virtual long Cleanup()
3376 glDeleteProgram(prog_);
3381 class NegativeUnsizedArray : public SACSubcaseBase
3383 virtual std::string Title()
3385 return NL "GLSL errors";
3388 virtual std::string Purpose()
3390 return NL "Verify that it is compile-time error to declare an unsized array of atomic_uint..";
3393 virtual std::string Method()
3398 virtual std::string PassCriteria()
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 "}";
3409 GLuint sh = glCreateShader(GL_FRAGMENT_SHADER);
3410 glShaderSource(sh, 1, &glsl_fs1, NULL);
3411 glCompileShader(sh);
3413 glGetShaderiv(sh, GL_COMPILE_STATUS, &status_comp);
3416 if (status_comp == GL_TRUE)
3418 m_context.getTestContext().getLog()
3419 << tcu::TestLog::Message << "Expected error during fragment shader compilation."
3420 << tcu::TestLog::EndMessage;
3428 class AdvancedManyDrawCalls2 : public SACSubcaseBase
3431 GLuint m_acbo, m_ssbo;
3433 GLuint m_ppo, m_vsp, m_fsp;
3435 virtual long Setup()
3437 glGenBuffers(1, &m_acbo);
3438 glGenBuffers(1, &m_ssbo);
3439 glGenVertexArrays(1, &m_vao);
3440 glGenProgramPipelines(1, &m_ppo);
3445 virtual long Cleanup()
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);
3460 glGetIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS, &p1);
3461 glGetIntegerv(GL_MAX_FRAGMENT_ATOMIC_COUNTERS, &p2);
3462 if (p1 < 1 || p2 < 1)
3465 "GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS or GL_MAX_FRAGMENT_ATOMIC_COUNTERS are less than required");
3466 return NOT_SUPPORTED;
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 "}";
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))
3481 glUseProgramStages(m_ppo, GL_VERTEX_SHADER_BIT, m_vsp);
3482 glUseProgramStages(m_ppo, GL_FRAGMENT_SHADER_BIT, m_fsp);
3484 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, m_acbo);
3487 glBufferData(GL_ATOMIC_COUNTER_BUFFER, 4, &data, GL_DYNAMIC_COPY);
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);
3497 glViewport(0, 0, 1, 1);
3498 glBindProgramPipeline(m_ppo);
3499 glBindVertexArray(m_vao);
3500 for (int i = 0; i < 100; ++i)
3502 glDrawArrays(GL_POINTS, 0, 1);
3505 glViewport(0, 0, getWindowWidth(), getWindowHeight());
3507 long status = NO_ERROR;
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));
3518 m_context.getTestContext().getLog() << tcu::TestLog::Message << "AC buffer content is " << data[0]
3519 << ", sholud be 100." << tcu::TestLog::EndMessage;
3521 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
3522 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
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)
3534 m_context.getTestContext().getLog() << tcu::TestLog::Message << "data[" << i << " is " << data[i]
3535 << ", sholud be " << i << tcu::TestLog::EndMessage;
3538 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3539 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
3546 class AdvancedUsageMultipleComputeDispatches : public SACSubcaseBase
3548 GLuint m_acbo, m_ssbo;
3549 GLuint m_ppo, m_csp;
3551 virtual long Setup()
3553 glGenBuffers(1, &m_acbo);
3554 glGenBuffers(1, &m_ssbo);
3555 glGenProgramPipelines(1, &m_ppo);
3560 virtual long Cleanup()
3562 glDeleteBuffers(1, &m_acbo);
3563 glDeleteBuffers(1, &m_ssbo);
3564 glDeleteProgramPipelines(1, &m_ppo);
3565 glDeleteProgram(m_csp);
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 "}";
3578 m_csp = glCreateShaderProgramv(GL_COMPUTE_SHADER, 1, &glsl_cs);
3579 if (!CheckProgram(m_csp))
3581 glUseProgramStages(m_ppo, GL_COMPUTE_SHADER_BIT, m_csp);
3583 glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, m_acbo);
3586 glBufferData(GL_ATOMIC_COUNTER_BUFFER, 4, &data, GL_DYNAMIC_COPY);
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);
3595 glBindProgramPipeline(m_ppo);
3596 for (int i = 0; i < 100; ++i)
3598 glDispatchCompute(1, 1, 1);
3601 long status = NO_ERROR;
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));
3612 m_context.getTestContext().getLog() << tcu::TestLog::Message << "AC buffer content is " << data[0]
3613 << ", sholud be 100" << tcu::TestLog::EndMessage;
3615 glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
3616 glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, 0);
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)
3628 m_context.getTestContext().getLog() << tcu::TestLog::Message << "data[" << i << "] is " << data[i]
3629 << ", sholud be " << i << tcu::TestLog::EndMessage;
3632 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3633 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
3640 class BasicGLSLBuiltIn : public BasicUsageCS
3643 virtual std::string Title()
3645 return NL "gl_Max* Check";
3647 virtual std::string Purpose()
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.";
3656 virtual long Setup()
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 "}";
3681 prog_ = CreateComputeProgram(glsl_cs);
3682 glLinkProgram(prog_);
3683 if (!CheckProgram(prog_))
3685 glUseProgram(prog_);
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);
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);
3708 glDispatchCompute(1, 1, 1);
3710 long error = NO_ERROR;
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));
3717 m_context.getTestContext().getLog()
3718 << tcu::TestLog::Message << "Expected 1, got: " << data[0] << tcu::TestLog::EndMessage;
3721 glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
3722 glBindBuffer(GL_SHADER_STORAGE_BUFFER, 0);
3727 virtual long Cleanup()
3729 glDeleteBuffers(1, &m_buffer);
3730 glDeleteProgram(prog_);
3736 ShaderAtomicCountersTests::ShaderAtomicCountersTests(glcts::Context& context)
3737 : TestCaseGroup(context, "shader_atomic_counters", "")
3741 ShaderAtomicCountersTests::~ShaderAtomicCountersTests(void)
3745 void ShaderAtomicCountersTests::init()
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>));
3763 new TestSubcase(m_context, "advanced-usage-many-counters", TestSubcase::Create<AdvancedUsageManyCounters>));
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>));
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>));