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