• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1Name
2
3    AMD_shader_atomic_counter_ops
4
5Name Strings
6
7    GL_AMD_shader_atomic_counter_ops
8
9Contact
10
11    Daniel Rakos (daniel.rakos 'at' amd.com)
12
13Contributors
14
15    Daniel Rakos, AMD
16    Graham Sellers, AMD
17
18Status
19
20    Shipping
21
22Version
23
24    Last Modified Date:         02/01/2013
25    Author Revision:            2
26
27Number
28
29    OpenGL Extension #435
30
31Dependencies
32
33    OpenGL 4.2 or ARB_shader_atomic_counters is required.
34
35    This extension is written against the OpenGL 4.3 (core) specification
36    and the GLSL 4.30.7 specification.
37
38Overview
39
40    The ARB_shader_atomic_counters extension introduced atomic counters, but
41    it limits list of potential operations that can be performed on them to
42    increment, decrement, and query. This extension extends the list of GLSL
43    built-in functions that can operate on atomic counters. The list of new
44    operations include:
45
46      * Increment and decrement with wrap
47      * Addition and subtraction
48      * Minimum and maximum
49      * Bitwise operators (AND, OR, XOR, etc.)
50      * Masked OR operator
51      * Exchange, and compare and exchange operators
52
53New Procedures and Functions
54
55    None.
56
57New Tokens
58
59    None.
60
61Additions to Chapter 8 of the GLSL 4.30.7 Specification (Built-in Functions)
62
63    Modify Section 8.10, Atomic-Counter Functions
64
65    Remove second paragraph ("The value returned by...")
66
67    Modify third paragraph ("The underlying...")
68
69      The underlying counter is a 32-bit unsigned integer. The result of
70      operations will wrap to [0, 2^32-1].
71
72    Additions to the table listing atomic counter built-in functions:
73
74      Syntax                                Description
75      ------------------------------------  ------------------------------------------------------------------
76      uint atomicCounterIncWrap(            Atomically
77          atomic_uint c,                      1. increments the counter for c, then forces it to zero if and
78          uint wrap                              only if the incremented value is greater than or equal to
79      )                                          <wrap>, and
80                                              2. returns its value prior to the operation.
81                                            These two steps are done atomically with respect to the atomic
82                                            counter functions in this table.
83
84      uint atomicCounterDecWrap(            Atomically
85          atomic_uint c,                      1. decrements the counter for c, then forces it to <wrap>-1 if
86          uint wrap                              and only if the original value of the counter was either
87      )                                          zero or greater than <wrap>, and
88                                              2. returns its value resulting from the operation.
89                                            These two steps are done atomically with respect to the atomic
90                                            counter functions in this table.
91
92      uint atomicCounterAdd(                Atomically
93          atomic_uint c,                      1. adds the value of <data> to the counter for c, and
94          uint data                           2. returns its value prior to the operation.
95      )                                     These two steps are done atomically with respect to the atomic
96                                            counter functions in this table.
97
98      uint atomicCounterSubtract(           Atomically
99          atomic_uint c,                      1. subtracts the value of <data> from the counter for c, and
100          uint data                           2. returns the value resulting from the operation.
101      )                                     These two steps are done atomically with respect to the atomic
102                                            counter functions in this table.
103
104      uint atomicCounterReverseSubtract(    Atomically
105          atomic_uint c,                      1. subtracts the value of the counter for c from the value of
106          uint data                              <data> and sets the counter for c to the result of the
107      )                                          operation, and
108                                              2. returns the value prior to the operation.
109                                            These two steps are done atomically with respect to the atomic
110                                            counter functions in this table.
111
112      uint atomicCounterMin(                Atomically
113          atomic_uint c,                      1. sets the counter for c to the minimum of the value of the
114          uint data                              counter and the value of <data>, and
115      )                                       2. returns the value prior to the operation.
116                                            These two steps are done atomically with respect to the atomic
117                                            counter functions in this table.
118
119      uint atomicCounterMax(                Atomically
120          atomic_uint c,                      1. sets the counter for c to the maximum of the value of the
121          uint data                              counter and the value of <data>, and
122      )                                       2. returns the value prior to the operation.
123                                            These two steps are done atomically with respect to the atomic
124                                            counter functions in this table.
125
126      uint atomicCounterAnd(                Atomically
127          atomic_uint c,                      1. sets the counter for c to the result of the bitwise AND of
128          uint data                              the value of the counter and the value of <data>, and
129      )                                       2. returns the value prior to the operation.
130                                            These two steps are done atomically with respect to the atomic
131                                            counter functions in this table.
132
133      uint atomicCounterOr(                 Atomically
134          atomic_uint c,                      1. sets the counter for c to the result of the bitwise OR of
135          uint data                              the value of the counter and the value of <data>, and
136      )                                       2. returns the value prior to the operation.
137                                            These two steps are done atomically with respect to the atomic
138                                            counter functions in this table.
139
140      uint atomicCounterXor(                Atomically
141          atomic_uint c,                      1. sets the counter for c to the result of the bitwise XOR of
142          uint data                              the value of the counter and the value of <data>, and
143      )                                       2. returns the value prior to the operation.
144                                            These two steps are done atomically with respect to the atomic
145                                            counter functions in this table.
146
147      uint atomicCounterMaskOr(             Atomically
148          atomic_uint c,                      1. sets the counter for c to the result of the operation:
149          uint mask,                               (counter ^ ~mask) | data
150          uint data                           2. returns the value prior to the operation.
151      )                                     These two steps are done atomically with respect to the atomic
152                                            counter functions in this table.
153
154      uint atomicCounterExchange(           Atomically
155          atomic_uint c,                      1. sets the counter value for c to the value of <data>, and
156          uint data                           2. returns its value prior to the operation.
157      )                                     These two steps are done atomically with respect to the atomic
158                                            counter functions in this table.
159
160      uint atomicCounterCompSwap(           Atomically
161          atomic_uint c,                      1. compares the value of <compare> and the counter value for c,
162          uint compare,                       2. if the values are equal, sets the counter value for c to
163          uint data                              the value of <data>, and
164      )                                       3. returns its value prior to the operation.
165                                            These three steps are done atomically with respect to the atomic
166                                            counter functions in this table.
167
168Additions to the AGL/GLX/WGL Specifications
169
170    None.
171
172GLX Protocol
173
174    None.
175
176Errors
177
178    None.
179
180New State
181
182    None.
183
184New Implementation Dependent State
185
186    None.
187
188Usage Examples
189
190    Example 1: Appending/consuming data to/from a ring buffer using a compute shader
191
192        // Here we use increment/decrement with wrap to account for the wrapping at the
193        // end of the ring buffer.
194        // Using regular increment/decrement and performing a modulo manually is not
195        // satisfactory for non-power-of-two sized buffers as when the 32-bit counter
196        // wraps around we get incorrect results.
197
198        // Append shader
199        layout(binding=0, offset=0) uniform atomic_uint ringCounter;
200        layout(binding=0, r32ui) uniform imageBuffer ringBuffer;
201
202        void main()
203        {
204            uint myBufferData = ...;
205
206            imageStore(ringBuffer,
207                       atomicCounterIncWrap(ringCounter, imageSize(ringBuffer)),
208                       myBufferData);
209        }
210
211        // Consume shader
212        layout(binding=0, offset=0) uniform atomic_uint ringCounter;
213        layout(binding=0, r32ui) uniform imageBuffer ringBuffer;
214
215        void main()
216        {
217            uint myBufferData =
218                imageLoad(ringBuffer,
219                          atomicCounterDecWrap(ringCounter, imageSize(ringBuffer))).x;
220        }
221
222    Example 2: Appending variable length records to a buffer using a compute shader
223
224        // Here we use atomicCounterAdd to ensure that we "allocate" a contiguous list of
225        // elements in the buffer.
226        // Using atomicCounterIncrement cannot mimic this behavior as there is no guarantee
227        // that subsequent calls to atomicCounterIncrement return subsequent counter values.
228
229        layout(binding=0, offset=0) uniform atomic_uint vlrCounter;
230        layout(binding=0, r32ui) uniform imageBuffer vlrBuffer;
231
232        void main()
233        {
234            uint data[...] = ...;
235            uint recordLength = ...;
236
237            uint recordStart = atomicCounterAdd(vlrCounter, recordLength);
238
239            for (uint i = 0; i < recordLength; ++i)
240            {
241                imageStore(vlrBuffer, recordStart + i, data[i]);
242            }
243        }
244
245Issues
246
247    1) Should the new decrement with wrap and subtract operators match the
248    behavior of the existing decrement operator and return the post-operation
249    value of the counter?
250
251    RESOLVED: Yes, for consistency with the existing functionality.
252
253    2) Most of the new operations introduced by this extension are already
254    supported on load/store images and shader storage buffers. What benefit
255    the application developer could get from using this extension?
256
257    DISCUSSION: Atomic counter operations can have different performance
258    characteristics than load/store images or shader storage buffers. It is
259    expected that implementations can do atomic counter operations faster.
260    Also, there is no increment/decrement with wrap, reverse subtract and
261    mask-or operation for these storages (though the EXT version of load/store
262    image extension does provide a increment/decrement with wrap operators).
263
264    RESOLVED: It enables existing operations for atomic counters and also
265    adds completely new operations that are not available for load/store
266    images and shader storage buffers.
267
268    3) What should be the result of the increment/decrement with wrap
269    operations if the original counter value is greater than the <wrap>
270    parameter?
271
272    RESOLVED: Increment with wrap will force the value of the counter to zero,
273    decrement with wrap will force the value of the counter to <wrap>-1.
274
275Revision History
276
277    Rev.    Date      Author    Changes
278    ----  --------    --------  ---------------------------------------------
279
280      2   02/01/2013  drakos    Added issue #2 and #3
281                                Cleaned up naming convention
282      1   11/13/2012  drakos    Initial revision
283