• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2017 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // AtomicCounterBufferTest:
7 //   Various tests related for atomic counter buffers.
8 //
9 
10 #include "test_utils/ANGLETest.h"
11 #include "test_utils/gl_raii.h"
12 
13 using namespace angle;
14 
15 namespace
16 {
17 
18 class AtomicCounterBufferTest : public ANGLETest
19 {
20   protected:
AtomicCounterBufferTest()21     AtomicCounterBufferTest()
22     {
23         setWindowWidth(128);
24         setWindowHeight(128);
25         setConfigRedBits(8);
26         setConfigGreenBits(8);
27         setConfigBlueBits(8);
28         setConfigAlphaBits(8);
29     }
30 };
31 
32 // Test GL_ATOMIC_COUNTER_BUFFER is not supported with version lower than ES31.
TEST_P(AtomicCounterBufferTest,AtomicCounterBufferBindings)33 TEST_P(AtomicCounterBufferTest, AtomicCounterBufferBindings)
34 {
35     ASSERT_EQ(3, getClientMajorVersion());
36     GLBuffer atomicCounterBuffer;
37     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer.get());
38     if (getClientMinorVersion() < 1)
39     {
40         EXPECT_GL_ERROR(GL_INVALID_ENUM);
41     }
42     else
43     {
44         EXPECT_GL_NO_ERROR();
45     }
46 }
47 
48 class AtomicCounterBufferTest31 : public AtomicCounterBufferTest
49 {};
50 
51 // Linking should fail if counters in vertex shader exceed gl_MaxVertexAtomicCounters.
TEST_P(AtomicCounterBufferTest31,ExceedMaxVertexAtomicCounters)52 TEST_P(AtomicCounterBufferTest31, ExceedMaxVertexAtomicCounters)
53 {
54     constexpr char kVS[] =
55         "#version 310 es\n"
56         "layout(binding = 0) uniform atomic_uint foo[gl_MaxVertexAtomicCounters + 1];\n"
57         "void main()\n"
58         "{\n"
59         "    atomicCounterIncrement(foo[0]);\n"
60         "}\n";
61     constexpr char kFS[] =
62         "#version 310 es\n"
63         "void main()\n"
64         "{\n"
65         "}\n";
66 
67     GLuint program = CompileProgram(kVS, kFS);
68     EXPECT_EQ(0u, program);
69 }
70 
71 // Counters matching across shader stages should fail if offsets aren't all specified.
72 // GLSL ES Spec 3.10.4, section 9.2.1.
TEST_P(AtomicCounterBufferTest31,OffsetNotAllSpecified)73 TEST_P(AtomicCounterBufferTest31, OffsetNotAllSpecified)
74 {
75     constexpr char kVS[] =
76         "#version 310 es\n"
77         "layout(binding = 0, offset = 4) uniform atomic_uint foo;\n"
78         "void main()\n"
79         "{\n"
80         "    atomicCounterIncrement(foo);\n"
81         "}\n";
82     constexpr char kFS[] =
83         "#version 310 es\n"
84         "layout(binding = 0) uniform atomic_uint foo;\n"
85         "void main()\n"
86         "{\n"
87         "}\n";
88 
89     GLuint program = CompileProgram(kVS, kFS);
90     EXPECT_EQ(0u, program);
91 }
92 
93 // Counters matching across shader stages should fail if offsets aren't all specified with same
94 // value.
TEST_P(AtomicCounterBufferTest31,OffsetNotAllSpecifiedWithSameValue)95 TEST_P(AtomicCounterBufferTest31, OffsetNotAllSpecifiedWithSameValue)
96 {
97     constexpr char kVS[] =
98         "#version 310 es\n"
99         "layout(binding = 0, offset = 4) uniform atomic_uint foo;\n"
100         "void main()\n"
101         "{\n"
102         "    atomicCounterIncrement(foo);\n"
103         "}\n";
104     constexpr char kFS[] =
105         "#version 310 es\n"
106         "layout(binding = 0, offset = 8) uniform atomic_uint foo;\n"
107         "void main()\n"
108         "{\n"
109         "}\n";
110 
111     GLuint program = CompileProgram(kVS, kFS);
112     EXPECT_EQ(0u, program);
113 }
114 
115 // Tests atomic counter reads using compute shaders. Used as a confidence check for the translator.
TEST_P(AtomicCounterBufferTest31,AtomicCounterReadCompute)116 TEST_P(AtomicCounterBufferTest31, AtomicCounterReadCompute)
117 {
118     // Skipping due to a bug on the Adreno OpenGLES Android driver.
119     // http://anglebug.com/2925
120     ANGLE_SKIP_TEST_IF(IsAndroid() && IsAdreno() && IsOpenGLES());
121 
122     constexpr char kComputeShaderSource[] = R"(#version 310 es
123 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
124 
125 void atomicCounterInFunction(in atomic_uint counter[3]);
126 
127 layout(binding = 0, offset = 8) uniform atomic_uint ac[3];
128 
129 void atomicCounterInFunction(in atomic_uint counter[3])
130 {
131     atomicCounter(counter[0]);
132 }
133 
134 void main()
135 {
136     atomicCounterInFunction(ac);
137     atomicCounter(ac[gl_LocalInvocationIndex + 1u]);
138 })";
139 
140     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
141     EXPECT_GL_NO_ERROR();
142 }
143 
144 // Test atomic counter read.
TEST_P(AtomicCounterBufferTest31,AtomicCounterRead)145 TEST_P(AtomicCounterBufferTest31, AtomicCounterRead)
146 {
147     // Skipping test while we work on enabling atomic counter buffer support in th D3D renderer.
148     // http://anglebug.com/1729
149     ANGLE_SKIP_TEST_IF(IsD3D11());
150 
151     constexpr char kFS[] =
152         "#version 310 es\n"
153         "precision highp float;\n"
154         "layout(binding = 0, offset = 4) uniform atomic_uint ac;\n"
155         "out highp vec4 my_color;\n"
156         "void main()\n"
157         "{\n"
158         "    my_color = vec4(0.0);\n"
159         "    uint a1 = atomicCounter(ac);\n"
160         "    if (a1 == 3u) my_color = vec4(1.0);\n"
161         "}\n";
162 
163     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
164 
165     glUseProgram(program.get());
166 
167     // The initial value of counter 'ac' is 3u.
168     unsigned int bufferData[3] = {11u, 3u, 1u};
169     GLBuffer atomicCounterBuffer;
170     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
171     glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(bufferData), bufferData, GL_STATIC_DRAW);
172 
173     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
174 
175     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.0f);
176     ASSERT_GL_NO_ERROR();
177     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
178 }
179 
180 // Test a bug in vulkan back-end where recreating the atomic counter storage should trigger state
181 // update in the context
TEST_P(AtomicCounterBufferTest31,DependentAtomicCounterBufferChange)182 TEST_P(AtomicCounterBufferTest31, DependentAtomicCounterBufferChange)
183 {
184     // Skipping test while we work on enabling atomic counter buffer support in th D3D renderer.
185     // http://anglebug.com/1729
186     ANGLE_SKIP_TEST_IF(IsD3D11());
187 
188     constexpr char kFS[] =
189         "#version 310 es\n"
190         "precision highp float;\n"
191         "layout(binding = 0, offset = 4) uniform atomic_uint ac;\n"
192         "out highp vec4 my_color;\n"
193         "void main()\n"
194         "{\n"
195         "    my_color = vec4(0.0);\n"
196         "    uint a1 = atomicCounter(ac);\n"
197         "    if (a1 == 3u) my_color = vec4(1.0);\n"
198         "    if (a1 == 19u) my_color = vec4(1.0, 0.0, 0.0, 1.0);\n"
199         "}\n";
200 
201     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
202 
203     glUseProgram(program.get());
204 
205     // The initial value of counter 'ac' is 3u.
206     unsigned int bufferDataLeft[3] = {11u, 3u, 1u};
207     GLBuffer atomicCounterBuffer;
208     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
209     glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(bufferDataLeft), bufferDataLeft, GL_STATIC_DRAW);
210 
211     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
212     // Draw left quad
213     glViewport(0, 0, getWindowWidth() / 2, getWindowHeight());
214     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.0f);
215     // Draw right quad
216     unsigned int bufferDataRight[3] = {11u, 19u, 1u};
217     glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(bufferDataRight), bufferDataRight,
218                  GL_STATIC_DRAW);
219     glViewport(getWindowWidth() / 2, 0, getWindowWidth() / 2, getWindowHeight());
220     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.0f);
221     ASSERT_GL_NO_ERROR();
222     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
223     EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 2, 0, GLColor::red);
224 }
225 
226 // Updating atomic counter buffer's offsets was optimized based on a count of valid bindings.
227 // This test will fail if there are bugs in how we count valid bindings.
TEST_P(AtomicCounterBufferTest31,AtomicCounterBufferRangeRead)228 TEST_P(AtomicCounterBufferTest31, AtomicCounterBufferRangeRead)
229 {
230     // Skipping due to a bug on the Qualcomm driver.
231     // http://anglebug.com/3726
232     ANGLE_SKIP_TEST_IF(IsNexus5X() && IsOpenGLES());
233 
234     // Skipping test while we work on enabling atomic counter buffer support in th D3D renderer.
235     // http://anglebug.com/1729
236     ANGLE_SKIP_TEST_IF(IsD3D11());
237 
238     constexpr char kFS[] =
239         "#version 310 es\n"
240         "precision highp float;\n"
241         "layout(binding = 0, offset = 4) uniform atomic_uint ac;\n"
242         "out highp vec4 my_color;\n"
243         "void main()\n"
244         "{\n"
245         "    my_color = vec4(0.0);\n"
246         "    uint a1 = atomicCounter(ac);\n"
247         "    if (a1 == 3u) my_color = vec4(1.0);\n"
248         "}\n";
249 
250     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
251 
252     glUseProgram(program.get());
253 
254     // The initial value of counter 'ac' is 3u.
255     unsigned int bufferData[]     = {0u, 0u, 0u, 0u, 0u, 11u, 3u, 1u};
256     constexpr GLintptr kOffset    = 20;
257     GLint maxAtomicCounterBuffers = 0;
258     GLBuffer atomicCounterBuffer;
259 
260     glGetIntegerv(GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS, &maxAtomicCounterBuffers);
261     // Repeatedly bind the same buffer (GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS + 1) times
262     // A bug in counting valid atomic counter buffers will cause a crash when we
263     // exceed GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS
264     for (int32_t i = 0; i < maxAtomicCounterBuffers + 1; i++)
265     {
266         glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
267         glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(bufferData), bufferData, GL_STATIC_DRAW);
268         glBindBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer, kOffset,
269                           sizeof(bufferData) - kOffset);
270     }
271 
272     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.0f);
273     ASSERT_GL_NO_ERROR();
274     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
275 }
276 
277 // Updating atomic counter buffer's offsets was optimized based on a count of valid bindings.
278 // Repeatedly bind/unbind buffers across available binding points. The test will fail if
279 // there are bugs in how we count valid bindings.
TEST_P(AtomicCounterBufferTest31,AtomicCounterBufferRepeatedBindUnbind)280 TEST_P(AtomicCounterBufferTest31, AtomicCounterBufferRepeatedBindUnbind)
281 {
282     // Skipping test while we work on enabling atomic counter buffer support in th D3D renderer.
283     // http://anglebug.com/1729
284     ANGLE_SKIP_TEST_IF(IsD3D11());
285 
286     constexpr char kFS[] =
287         "#version 310 es\n"
288         "precision highp float;\n"
289         "layout(binding = 0, offset = 4) uniform atomic_uint ac;\n"
290         "out highp vec4 my_color;\n"
291         "void main()\n"
292         "{\n"
293         "    my_color = vec4(0.0);\n"
294         "    uint a1 = atomicCounter(ac);\n"
295         "    if (a1 == 3u) my_color = vec4(1.0);\n"
296         "}\n";
297 
298     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
299 
300     glUseProgram(program.get());
301 
302     constexpr int32_t kBufferCount = 16;
303     // The initial value of counter 'ac' is 3u.
304     unsigned int bufferData[3] = {11u, 3u, 1u};
305     GLBuffer atomicCounterBuffer[kBufferCount];
306     // Populate atomicCounterBuffer[0] with valid data and the rest with nullptr
307     for (int32_t bufferIndex = 0; bufferIndex < kBufferCount; bufferIndex++)
308     {
309         glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer[bufferIndex]);
310         glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(bufferData),
311                      (bufferIndex == 0) ? bufferData : nullptr, GL_STATIC_DRAW);
312     }
313 
314     GLint maxAtomicCounterBuffers = 0;
315     glGetIntegerv(GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS, &maxAtomicCounterBuffers);
316 
317     // Cycle through multiple buffers
318     for (int32_t i = 0; i < kBufferCount; i++)
319     {
320         constexpr int32_t kBufferIndices[kBufferCount] = {7, 12, 15, 5, 13, 14, 1, 2,
321                                                           0, 6,  4,  9, 8,  11, 3, 10};
322         int32_t bufferIndex                            = kBufferIndices[i];
323 
324         // Randomly bind/unbind buffers to/from different binding points,
325         // capped by GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS
326         for (int32_t bufferCount = 0; bufferCount < maxAtomicCounterBuffers; bufferCount++)
327         {
328             constexpr uint32_t kBindingSlotsSize                = kBufferCount;
329             constexpr uint32_t kBindingSlots[kBindingSlotsSize] = {1,  3,  4, 14, 15, 9, 0, 6,
330                                                                    12, 11, 8, 5,  10, 2, 7, 13};
331 
332             uint32_t bindingSlotIndex = bufferCount % kBindingSlotsSize;
333             uint32_t bindingSlot      = kBindingSlots[bindingSlotIndex];
334             uint32_t bindingPoint     = bindingSlot % maxAtomicCounterBuffers;
335             bool even                 = (bufferCount % 2 == 0);
336             int32_t bufferId          = (even) ? 0 : atomicCounterBuffer[bufferIndex];
337 
338             glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, bindingPoint, bufferId);
339         }
340     }
341 
342     // Bind atomicCounterBuffer[0] to slot 0 and verify result
343     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer[0]);
344     drawQuad(program.get(), essl31_shaders::PositionAttrib(), 0.0f);
345     ASSERT_GL_NO_ERROR();
346     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::white);
347 }
348 
349 // Test atomic counter increment and decrement.
TEST_P(AtomicCounterBufferTest31,AtomicCounterIncrementAndDecrement)350 TEST_P(AtomicCounterBufferTest31, AtomicCounterIncrementAndDecrement)
351 {
352     constexpr char kCS[] =
353         "#version 310 es\n"
354         "layout(local_size_x=1, local_size_y=1, local_size_z=1) in;\n"
355         "layout(binding = 0, offset = 4) uniform atomic_uint ac[2];\n"
356         "void main()\n"
357         "{\n"
358         "    atomicCounterIncrement(ac[0]);\n"
359         "    atomicCounterDecrement(ac[1]);\n"
360         "}\n";
361 
362     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
363 
364     glUseProgram(program.get());
365 
366     // The initial value of 'ac[0]' is 3u, 'ac[1]' is 1u.
367     unsigned int bufferData[3] = {11u, 3u, 1u};
368     GLBuffer atomicCounterBuffer;
369     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
370     glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(bufferData), bufferData, GL_STATIC_DRAW);
371 
372     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
373 
374     glDispatchCompute(1, 1, 1);
375     EXPECT_GL_NO_ERROR();
376 
377     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
378 
379     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
380     void *mappedBuffer =
381         glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(GLuint) * 3, GL_MAP_READ_BIT);
382     memcpy(bufferData, mappedBuffer, sizeof(bufferData));
383     glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
384 
385     EXPECT_EQ(11u, bufferData[0]);
386     EXPECT_EQ(4u, bufferData[1]);
387     EXPECT_EQ(0u, bufferData[2]);
388 }
389 
390 // Tests multiple atomic counter buffers.
TEST_P(AtomicCounterBufferTest31,AtomicCounterMultipleBuffers)391 TEST_P(AtomicCounterBufferTest31, AtomicCounterMultipleBuffers)
392 {
393     GLint maxAtomicCounterBuffers = 0;
394     glGetIntegerv(GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS, &maxAtomicCounterBuffers);
395     constexpr unsigned int kBufferCount = 3;
396     // ES 3.1 table 20.45 only guarantees 1 atomic counter buffer
397     ANGLE_SKIP_TEST_IF(maxAtomicCounterBuffers < static_cast<int>(kBufferCount));
398 
399     constexpr char kComputeShaderSource[] = R"(#version 310 es
400 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
401 layout(binding = 0) uniform atomic_uint ac1;
402 layout(binding = 1) uniform atomic_uint ac2;
403 layout(binding = 2) uniform atomic_uint ac3;
404 
405 void main()
406 {
407     atomicCounterIncrement(ac1);
408     atomicCounterIncrement(ac2);
409     atomicCounterIncrement(ac3);
410 })";
411 
412     ANGLE_GL_COMPUTE_PROGRAM(program, kComputeShaderSource);
413 
414     glUseProgram(program);
415 
416     GLBuffer atomicCounterBuffers[kBufferCount];
417 
418     for (unsigned int ii = 0; ii < kBufferCount; ++ii)
419     {
420         GLuint initialData[1] = {ii};
421         glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffers[ii]);
422         glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(initialData), initialData, GL_STATIC_DRAW);
423 
424         glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, ii, atomicCounterBuffers[ii]);
425     }
426 
427     glDispatchCompute(1, 1, 1);
428     EXPECT_GL_NO_ERROR();
429 
430     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
431 
432     for (unsigned int ii = 0; ii < kBufferCount; ++ii)
433     {
434         glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffers[ii]);
435         GLuint *mappedBuffer = static_cast<GLuint *>(
436             glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(GLuint), GL_MAP_READ_BIT));
437         EXPECT_EQ(ii + 1, mappedBuffer[0]);
438         glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
439     }
440 }
441 
442 // Test atomic counter array of array.
TEST_P(AtomicCounterBufferTest31,AtomicCounterArrayOfArray)443 TEST_P(AtomicCounterBufferTest31, AtomicCounterArrayOfArray)
444 {
445     // Fails on D3D.  Some counters are double-incremented while some are untouched, hinting at a
446     // bug in index translation.  http://anglebug.com/3783
447     ANGLE_SKIP_TEST_IF(IsD3D11());
448 
449     // Nvidia's OpenGL driver fails to compile the shader.  http://anglebug.com/3791
450     ANGLE_SKIP_TEST_IF(IsOpenGL() && IsNVIDIA());
451 
452     // Intel's Windows OpenGL driver crashes in this test.  http://anglebug.com/3791
453     ANGLE_SKIP_TEST_IF(IsOpenGL() && IsIntel() && IsWindows());
454 
455     constexpr char kCS[] = R"(#version 310 es
456 layout(local_size_x=1, local_size_y=1, local_size_z=1) in;
457 layout(binding = 0) uniform atomic_uint ac[7][5][3];
458 
459 void f0(in atomic_uint ac)
460 {
461     atomicCounterIncrement(ac);
462 }
463 
464 void f1(in atomic_uint ac[3])
465 {
466     atomicCounterIncrement(ac[0]);
467     f0(ac[1]);
468     int index = 2;
469     f0(ac[index]);
470 }
471 
472 void f2(in atomic_uint ac[5][3])
473 {
474     // Increment all in ac[0], ac[1] and ac[2]
475     for (int i = 0; i < 3; ++i)
476     {
477         for (int j = 0; j < 2; ++j)
478         {
479             f0(ac[i][j]);
480         }
481         f0(ac[i][2]);
482     }
483 
484     // Increment all in ac[3]
485     f1(ac[3]);
486 
487     // Increment all in ac[4]
488     for (int i = 0; i < 2; ++i)
489     {
490         atomicCounterIncrement(ac[4][i]);
491     }
492     f0(ac[4][2]);
493 }
494 
495 void f3(in atomic_uint ac[7][5][3])
496 {
497     // Increment all in ac[0], ac[1], ac[2] and ac[3]
498     f2(ac[0]);
499     for (int i = 1; i < 4; ++i)
500     {
501         f2(ac[i]);
502     }
503 
504     // Increment all in ac[5][0], ac[5][1], ac[5][2] and ac[5][3]
505     for (int i = 0; i < 4; ++i)
506     {
507         f1(ac[5][i]);
508     }
509 
510     // Increment all in ac[5][4][0], ac[5][4][1] and ac[5][4][2]
511     f0(ac[5][4][0]);
512     for (int i = 1; i < 3; ++i)
513     {
514         f0(ac[5][4][i]);
515     }
516 
517     // Increment all in ac[6]
518     for (int i = 0; i < 5; ++i)
519     {
520         for (int j = 0; j < 2; ++j)
521         {
522             atomicCounterIncrement(ac[6][i][j]);
523         }
524         atomicCounterIncrement(ac[6][i][2]);
525     }
526 }
527 
528 void main()
529 {
530     // Increment all in ac except ac[4]
531     f3(ac);
532 
533     // Increment all in ac[4]
534     f2(ac[4]);
535 })";
536 
537     constexpr uint32_t kAtomicCounterRows  = 7;
538     constexpr uint32_t kAtomicCounterCols  = 5;
539     constexpr uint32_t kAtomicCounterDepth = 3;
540     constexpr uint32_t kAtomicCounterCount =
541         kAtomicCounterRows * kAtomicCounterCols * kAtomicCounterDepth;
542 
543     GLint maxAtomicCounters = 0;
544     glGetIntegerv(GL_MAX_COMPUTE_ATOMIC_COUNTERS, &maxAtomicCounters);
545     EXPECT_GL_NO_ERROR();
546 
547     // Required minimum is 8 by the spec
548     EXPECT_GE(maxAtomicCounters, 8);
549     ANGLE_SKIP_TEST_IF(static_cast<uint32_t>(maxAtomicCounters) < kAtomicCounterCount);
550 
551     ANGLE_GL_COMPUTE_PROGRAM(program, kCS);
552     glUseProgram(program.get());
553 
554     // The initial value of atomic counters is 0, 1, 2, ...
555     unsigned int bufferData[kAtomicCounterCount] = {};
556     for (uint32_t index = 0; index < kAtomicCounterCount; ++index)
557     {
558         bufferData[index] = index;
559     }
560 
561     GLBuffer atomicCounterBuffer;
562     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
563     glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(bufferData), bufferData, GL_STATIC_DRAW);
564 
565     glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, atomicCounterBuffer);
566 
567     glDispatchCompute(1, 1, 1);
568     EXPECT_GL_NO_ERROR();
569 
570     glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT);
571 
572     unsigned int result[kAtomicCounterCount] = {};
573     glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
574     void *mappedBuffer =
575         glMapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(bufferData), GL_MAP_READ_BIT);
576     memcpy(result, mappedBuffer, sizeof(bufferData));
577     glUnmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
578 
579     for (uint32_t index = 0; index < kAtomicCounterCount; ++index)
580     {
581         EXPECT_EQ(result[index], bufferData[index] + 1) << "index " << index;
582     }
583 }
584 
585 // Test inactive atomic counter
TEST_P(AtomicCounterBufferTest31,AtomicCounterInactive)586 TEST_P(AtomicCounterBufferTest31, AtomicCounterInactive)
587 {
588     constexpr char kFS[] =
589         "#version 310 es\n"
590         "precision highp float;\n"
591 
592         // This inactive atomic counter should be removed by RemoveInactiveInterfaceVariables
593         "layout(binding = 0) uniform atomic_uint inactive;\n"
594 
595         "out highp vec4 my_color;\n"
596         "void main()\n"
597         "{\n"
598         "    my_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
599         "}\n";
600 
601     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
602     glUseProgram(program);
603 
604     drawQuad(program, essl31_shaders::PositionAttrib(), 0.0f);
605     ASSERT_GL_NO_ERROR();
606 
607     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
608 }
609 
610 // Test inactive memoryBarrierAtomicCounter
TEST_P(AtomicCounterBufferTest31,AtomicCounterMemoryBarrier)611 TEST_P(AtomicCounterBufferTest31, AtomicCounterMemoryBarrier)
612 {
613     constexpr char kFS[] =
614         "#version 310 es\n"
615         "precision highp float;\n"
616         // This inactive atomic counter should be removed by RemoveInactiveInterfaceVariables
617         "layout(binding = 0) uniform atomic_uint inactive;\n"
618         "out highp vec4 my_color;\n"
619         "void main()\n"
620         "{\n"
621         "    my_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
622         // This barrier should be removed by RemoveAtomicCounterBuiltins because
623         // there are no active atomic counters
624         "    memoryBarrierAtomicCounter();\n"
625         "}\n";
626 
627     ANGLE_GL_PROGRAM(program, essl31_shaders::vs::Simple(), kFS);
628     glUseProgram(program);
629 
630     drawQuad(program, essl31_shaders::PositionAttrib(), 0.0f);
631     ASSERT_GL_NO_ERROR();
632 
633     EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
634 }
635 
636 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AtomicCounterBufferTest);
637 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AtomicCounterBufferTest31);
638 ANGLE_INSTANTIATE_TEST_ES3_AND_ES31(AtomicCounterBufferTest);
639 ANGLE_INSTANTIATE_TEST_ES31(AtomicCounterBufferTest31);
640 
641 }  // namespace
642