1[require]
2GL >= 3.3
3GLSL >= 3.30
4GL_ARB_shader_storage_buffer_object
5GL_ARB_shader_atomic_counters
6GL_ARB_shader_atomic_counter_ops
7
8[vertex shader passthrough]
9
10[fragment shader]
11#version 330
12#extension GL_ARB_shader_storage_buffer_object: require
13#extension GL_ARB_shader_atomic_counters: require
14#extension GL_ARB_shader_atomic_counter_ops: require
15
16layout(binding = 0) buffer bufblock {
17       int value;
18};
19
20/* GL_ARB_shader_atomic_counters requires at least 8 total counters. */
21layout(binding = 0) uniform atomic_uint mask[7];
22layout(binding = 0) uniform atomic_uint fail;
23
24out vec4 color;
25
26const uint max_index = uint(mask.length()) * 32u + 31u;
27
28void main()
29{
30	uint x = uint(gl_FragCoord.x);
31	uint y = uint(gl_FragCoord.y);
32	uint local_index = y * 32u + x;
33
34	int new_value = (x < 32u && y < uint(mask.length()))
35		? int(4u * local_index) : 0x7fffffff;
36
37	int f = atomicExchange(value, new_value);
38	uint i = uint(f) / 4u;
39	uint bit = i % 32u;
40	int c = int(i / 32u);
41	uint m = 1u << bit;
42
43	if (i <= max_index) {
44		/* If the bit was already set, the test fails. */
45		uint r = atomicCounterOrARB(mask[c], m);
46		if ((r & m) != 0u)
47			atomicCounterIncrement(fail);
48
49		if (bit == local_index)
50			atomicCounterIncrement(fail);
51
52		color = vec4(0.0, 1.0, 0.0, 1.0);
53	} else {
54		color = vec4(0.0, 0.0, 1.0, 1.0);
55	}
56}
57
58[test]
59atomic counters 8
60
61ssbo 0 32
62ssbo 0 subdata int 0 65536
63
64clear color 0.5 0.5 0.5 0.5
65clear
66
67draw rect -1 -1 2 2
68
69probe atomic counter 0 == 4294967295
70probe atomic counter 1 == 4294967295
71probe atomic counter 2 == 4294967295
72probe atomic counter 3 == 4294967295
73probe atomic counter 4 == 4294967295
74probe atomic counter 5 == 4294967295
75probe atomic counter 6 == 4294967295
76probe atomic counter 7 == 0
77