@@ -185,6 +185,137 @@ TEST_P(AtomicCounterBufferTest31, AtomicCounterRead)
185
185
EXPECT_PIXEL_COLOR_EQ (0 , 0 , GLColor::white);
186
186
}
187
187
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
+
188
319
// Test atomic counter increment and decrement.
189
320
TEST_P (AtomicCounterBufferTest31, AtomicCounterIncrementAndDecrement)
190
321
{
0 commit comments