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