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