@@ -185,6 +185,137 @@ TEST_P(AtomicCounterBufferTest31, AtomicCounterRead)
185185 EXPECT_PIXEL_COLOR_EQ (0 , 0 , GLColor::white);
186186}
187187
188+ // Updating atomic counter buffer's offsets was optimized based on a count of valid bindings.
189+ // This test will fail if there are bugs in how we count valid bindings.
190+ TEST_P (AtomicCounterBufferTest31, AtomicCounterBufferRangeRead)
191+ {
192+ // Skipping due to a bug on the Qualcomm driver.
193+ // http://anglebug.com/3726
194+ ANGLE_SKIP_TEST_IF (IsNexus5X ());
195+
196+ // Skipping due to a bug on the Qualcomm Vulkan Android driver.
197+ // http://anglebug.com/3726
198+ ANGLE_SKIP_TEST_IF (IsAndroid () && IsVulkan ());
199+
200+ // Skipping test while we work on enabling atomic counter buffer support in th D3D renderer.
201+ // http://anglebug.com/1729
202+ ANGLE_SKIP_TEST_IF (IsD3D11 ());
203+
204+ constexpr char kFS [] =
205+ " #version 310 es\n "
206+ " precision highp float;\n "
207+ " layout(binding = 0, offset = 4) uniform atomic_uint ac;\n "
208+ " out highp vec4 my_color;\n "
209+ " void main()\n "
210+ " {\n "
211+ " my_color = vec4(0.0);\n "
212+ " uint a1 = atomicCounter(ac);\n "
213+ " if (a1 == 3u) my_color = vec4(1.0);\n "
214+ " }\n " ;
215+
216+ ANGLE_GL_PROGRAM (program, essl31_shaders::vs::Simple (), kFS );
217+
218+ glUseProgram (program.get ());
219+
220+ // The initial value of counter 'ac' is 3u.
221+ unsigned int bufferData[] = {0u , 0u , 0u , 0u , 0u , 11u , 3u , 1u };
222+ constexpr GLintptr kOffset = 20 ;
223+ GLint maxAtomicCounterBuffers = 0 ;
224+ GLBuffer atomicCounterBuffer;
225+
226+ glGetIntegerv (GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS, &maxAtomicCounterBuffers);
227+ // Repeatedly bind the same buffer (GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS + 1) times
228+ // A bug in counting valid atomic counter buffers will cause a crash when we
229+ // exceed GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS
230+ for (int32_t i = 0 ; i < maxAtomicCounterBuffers + 1 ; i++)
231+ {
232+ glBindBuffer (GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer);
233+ glBufferData (GL_ATOMIC_COUNTER_BUFFER, sizeof (bufferData), bufferData, GL_STATIC_DRAW);
234+ glBindBufferRange (GL_ATOMIC_COUNTER_BUFFER, 0 , atomicCounterBuffer, kOffset ,
235+ sizeof (bufferData) - kOffset );
236+ }
237+
238+ drawQuad (program.get (), essl31_shaders::PositionAttrib (), 0 .0f );
239+ ASSERT_GL_NO_ERROR ();
240+ EXPECT_PIXEL_COLOR_EQ (0 , 0 , GLColor::white);
241+ }
242+
243+ // Updating atomic counter buffer's offsets was optimized based on a count of valid bindings.
244+ // Repeatedly bind/unbind buffers across available binding points. The test will fail if
245+ // there are bugs in how we count valid bindings.
246+ TEST_P (AtomicCounterBufferTest31, AtomicCounterBufferRepeatedBindUnbind)
247+ {
248+ // Skipping due to a bug on the Qualcomm Vulkan Android driver.
249+ // http://anglebug.com/3726
250+ ANGLE_SKIP_TEST_IF (IsAndroid () && IsVulkan ());
251+
252+ // Skipping test while we work on enabling atomic counter buffer support in th D3D renderer.
253+ // http://anglebug.com/1729
254+ ANGLE_SKIP_TEST_IF (IsD3D11 ());
255+
256+ constexpr char kFS [] =
257+ " #version 310 es\n "
258+ " precision highp float;\n "
259+ " layout(binding = 0, offset = 4) uniform atomic_uint ac;\n "
260+ " out highp vec4 my_color;\n "
261+ " void main()\n "
262+ " {\n "
263+ " my_color = vec4(0.0);\n "
264+ " uint a1 = atomicCounter(ac);\n "
265+ " if (a1 == 3u) my_color = vec4(1.0);\n "
266+ " }\n " ;
267+
268+ ANGLE_GL_PROGRAM (program, essl31_shaders::vs::Simple (), kFS );
269+
270+ glUseProgram (program.get ());
271+
272+ constexpr int32_t kBufferCount = 16 ;
273+ // The initial value of counter 'ac' is 3u.
274+ unsigned int bufferData[3 ] = {11u , 3u , 1u };
275+ GLBuffer atomicCounterBuffer[kBufferCount ];
276+ // Populate atomicCounterBuffer[0] with valid data and the rest with nullptr
277+ for (int32_t bufferIndex = 0 ; bufferIndex < kBufferCount ; bufferIndex++)
278+ {
279+ glBindBuffer (GL_ATOMIC_COUNTER_BUFFER, atomicCounterBuffer[bufferIndex]);
280+ glBufferData (GL_ATOMIC_COUNTER_BUFFER, sizeof (bufferData),
281+ (bufferIndex == 0 ) ? bufferData : nullptr , GL_STATIC_DRAW);
282+ }
283+
284+ GLint maxAtomicCounterBuffers = 0 ;
285+ glGetIntegerv (GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS, &maxAtomicCounterBuffers);
286+
287+ // Cycle through multiple buffers
288+ for (int32_t i = 0 ; i < kBufferCount ; i++)
289+ {
290+ constexpr int32_t kBufferIndices [kBufferCount ] = {7 , 12 , 15 , 5 , 13 , 14 , 1 , 2 ,
291+ 0 , 6 , 4 , 9 , 8 , 11 , 3 , 10 };
292+ int32_t bufferIndex = kBufferIndices [i];
293+
294+ // Randomly bind/unbind buffers to/from different binding points,
295+ // capped by GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS
296+ for (int32_t bufferCount = 0 ; bufferCount < maxAtomicCounterBuffers; bufferCount++)
297+ {
298+ constexpr uint32_t kBindingSlotsSize = kBufferCount ;
299+ constexpr uint32_t kBindingSlots [kBindingSlotsSize ] = {1 , 3 , 4 , 14 , 15 , 9 , 0 , 6 ,
300+ 12 , 11 , 8 , 5 , 10 , 2 , 7 , 13 };
301+
302+ uint32_t bindingSlotIndex = bufferCount % kBindingSlotsSize ;
303+ uint32_t bindingSlot = kBindingSlots [bindingSlotIndex];
304+ uint32_t bindingPoint = bindingSlot % maxAtomicCounterBuffers;
305+ bool even = (bufferCount % 2 == 0 );
306+ int32_t bufferId = (even) ? 0 : atomicCounterBuffer[bufferIndex];
307+
308+ glBindBufferBase (GL_ATOMIC_COUNTER_BUFFER, bindingPoint, bufferId);
309+ }
310+ }
311+
312+ // Bind atomicCounterBuffer[0] to slot 0 and verify result
313+ glBindBufferBase (GL_ATOMIC_COUNTER_BUFFER, 0 , atomicCounterBuffer[0 ]);
314+ drawQuad (program.get (), essl31_shaders::PositionAttrib (), 0 .0f );
315+ ASSERT_GL_NO_ERROR ();
316+ EXPECT_PIXEL_COLOR_EQ (0 , 0 , GLColor::white);
317+ }
318+
188319// Test atomic counter increment and decrement.
189320TEST_P (AtomicCounterBufferTest31, AtomicCounterIncrementAndDecrement)
190321{
0 commit comments