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