Name ARB_shader_atomic_counters Name Strings GL_ARB_shader_atomic_counters Contact Bill Licea-Kane ( bill.licea-kane 'at' amd.com ) Contributors Barthold Lichtenbelt, NVIDIA Chris Dodd, NVIDIA Eric Werness, NVIDIA Graham Sellers, AMD Greg Roth, NVIDIA Jeff Bolz, NVIDIA Nick Haemel, AMD Pat Brown, NVIDIA Pierre Boudier, AMD Piers Daniell, NVIDIA Notice Copyright (c) 2011-2013 The Khronos Group Inc. Copyright terms at http://www.khronos.org/registry/speccopyright.html Specification Update Policy Khronos-approved extension specifications are updated in response to issues and bugs prioritized by the Khronos OpenGL Working Group. For extensions which have been promoted to a core Specification, fixes will first appear in the latest version of that core Specification, and will eventually be backported to the extension document. This policy is described in more detail at https://www.khronos.org/registry/OpenGL/docs/update_policy.php Status Complete. Approved by the ARB on 2011/06/20. Approved by the Khronos Promoters on 2011/07/29. Version Last Modified Date: July 30, 2012 Author Revision: 31 Number ARB Extension #114 Dependencies This extension is written against the OpenGL 4.1 (core) specification and the GLSL 4.10.6 specification. OpenGL 3.0 is required. Overview This extension provides a set of atomic counters. This extension provides GLSL built-in functions to query and increment/decrement these atomic counters. This enables a shader to write to unique offsets (append to a buffer object) or read from unique offsets (consume from a buffer object). Opaque handles to atomic counters are declared at global scope and are qualified with the uniform qualifier. Unlike other user-defined uniforms declared at global scope, they take NO storage from the default partition, they have NO location, and they may NOT be set with the Uniform* commands. Atomic counters may also NOT be grouped into uniform blocks. Active atomic counters can be discovered by the commands GetUniformIndices, GetActiveUniformName, GetActiveUniform and GetActiveUniformsiv. Like samplers, the opaque handles of the atomic counters and are ONLY used in some GLSL built-in functions. The atomic counters pointed to by the opaque handles are bound to buffer binding points and buffer offsets through the layout qualifiers in the shading language, or they are implicitly assigned by the compiler. Through the OpenGL API, buffer objects may be bound to these binding points with BindBufferBase or BindBufferRange. The contents of the atomic counters are stored in the buffer objects. The contents of atomic counters may be set and queried with buffer object manipulation functions (e.g. BufferData, BufferSubData, MapBuffer or MapBufferRange). IP Status No known IP claims. New Procedures and Functions void GetActiveAtomicCounterBufferiv (uint program, uint bufferIndex, enum pname, int *params); New Types None. New Tokens Accepted by the parameter of BindBufferBase and BindBufferRange: ATOMIC_COUNTER_BUFFER 0x92C0 Accepted by the parameter of GetBooleani_v, GetIntegeri_v, GetFloati_v, GetDoublei_v, GetInteger64i_v, GetBooleanv, GetIntegerv, GetInteger64v, GetFloatv, GetDoublev, and GetActiveAtomicCounterBufferiv: ATOMIC_COUNTER_BUFFER_BINDING 0x92C1 Accepted by the parameter of GetIntegeri_64v: ATOMIC_COUNTER_BUFFER_START 0x92C2 ATOMIC_COUNTER_BUFFER_SIZE 0x92C3 Accepted by the parameter of GetActiveAtomicCounterBufferiv: ATOMIC_COUNTER_BUFFER_DATA_SIZE 0x92C4 ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS 0x92C5 ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES 0x92C6 ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER 0x92C7 ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER 0x92C8 ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_EVALUATION_SHADER 0x92C9 ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER 0x92CA ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER 0x92CB Accepted by the parameter of GetBooleanv, GetIntegerv, GetInteger64v, GetFloatv, and GetDoublev: MAX_VERTEX_ATOMIC_COUNTER_BUFFERS 0x92CC MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS 0x92CD MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS 0x92CE MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS 0x92CF MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS 0x92D0 MAX_COMBINED_ATOMIC_COUNTER_BUFFERS 0x92D1 MAX_VERTEX_ATOMIC_COUNTERS 0x92D2 MAX_TESS_CONTROL_ATOMIC_COUNTERS 0x92D3 MAX_TESS_EVALUATION_ATOMIC_COUNTERS 0x92D4 MAX_GEOMETRY_ATOMIC_COUNTERS 0x92D5 MAX_FRAGMENT_ATOMIC_COUNTERS 0x92D6 MAX_COMBINED_ATOMIC_COUNTERS 0x92D7 MAX_ATOMIC_COUNTER_BUFFER_SIZE 0x92D8 MAX_ATOMIC_COUNTER_BUFFER_BINDINGS 0x92DC Accepted by the parameter of GetProgramiv: ACTIVE_ATOMIC_COUNTER_BUFFERS 0x92D9 Accepted by the parameter of GetActiveUniformsiv: UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX 0x92DA Returned in by GetActiveUniform and GetActiveUniformsiv: UNSIGNED_INT_ATOMIC_COUNTER 0x92DB Additions to Chapter 2 of the OpenGL 4.1 (Core Profile) Specification (OpenGL Operation) Changes to Section 2.9 Buffer Objects Add to table 2.8 (p. 41) Target Name Purpose Described in section(s) --------------------- ---------------------- ----------------------- ATOMIC_COUNTER_BUFFER Atomic counter storage 2.11.8 Changes to Section Binding Buffer Objects to Indexed Targets Change end of first sentence in section, p. 42 ...target must be ATOMIC_COUNTER_BUFFER, TRANSFORM_FEEDBACK_BUFFER or UNIFORM_BUFFER. 2.11.7 Uniform Variables Replace third sentence of paragraph one in the section, p. 72 beginning with "Uniforms are program..." Uniforms, except for subroutine uniforms, are program... Replace first sentence of paragraph two in the section, p. 72 beginning with "Sets of uniforms can be..." Sets of uniforms, except for samplers, subroutine uniforms and atomic counters, can be grouped into . Modify first sentence of first paragraph, p. 73 beginning with "The amount of storage..." The amount of storage available for uniform variables, except for subroutine uniforms and atomic counters, in the default uniform block... Modify first sentence of second paragraph, p. 73 beginning with "When a program..." When a program is successfully linked, all active uniforms, except for atomic counters, ... Insert a pragraph prior to third paragraph, p. 73 beginning with "Similary, when a program..." Similarly, when a program is successfully linked, all active atomic counters are assigned bindings, offsets (and strides for arrays of atomic counters) according to layout rules described below. Atomic counter uniform buffer objects provide the storage for atomic counters, so the values of atomic counters may be changed by modifying the contents of the buffer object using commands such as BufferData, BufferSubData, MapBuffer, and UnmapBuffer. Atomic counters are not assigned a location and may not be modified using the Uniform* commands. The bindings, offsets, and strides belonging to atomic counters of a program object are invalidated and new ones assigned after each successful re-link. Modify the final line on paragraph continuing on p. 74 ending "or if is associated with a named uniform block." ... if is associated with an atomic counter, or if is associated with a named uniform block. Insert section prior to the last paragraph on p. 76, begining with "Each active uniform, whether in a named..." In programs with active atomic counter uniforms, each buffer object binding point associated with one or more active atomic counters is considered an active atomic counter buffer. Information about the set of active atomic counter buffers for a program can be obtained by calling void GetActiveAtomicCounterBufferiv ( uint program, uint bufferIndex, enum pname, int *params ); is the name of a program object for which the command LinkProgram has been issued in the past. It is not necessary for to have been linked successfully. The link could have failed because the number of active active atomic counters exceeded implementation-dependent limits. specifies the index of an active atomic counter buffer and must be in the range zero to the value of ACTIVE_ATOMIC_COUNTER_BUFFERS-1. The value of ACTIVE_ATOMIC_COUNTER_BUFFERS for indicates the number of active atomic counter buffers and can be queried with GetProgramiv (see section 6.1.12). If is greater than or equal to the value of ACTIVE_ATOMIC_COUNTER_BUFFERS, the error INVALID_VALUE is generated. If no error occurs, the parameter(s) specified by are returned in . Otherwise, nothing will be written to . If is ATOMIC_COUNTER_BUFFER_BINDING, then the index of the atomic counter buffer binding point associated with the active atomic counter buffer for is returned. If is ATOMIC_COUNTER_BUFFER_DATA_SIZE, then the implementation-dependent minimum total buffer object size, in basic machine units, required to hold all active atomic counters in the atomic counter buffer identified by is returned. The total amount of buffer object storage accessible in any given atomic counter buffer is subject to an implementation-dependent limit. The maximum amount of storage accessible to atomic counters, in basic machine units, can be queried by calling GetIntegerv with the constant MAX_ATOMIC_COUNTER_BUFFER_SIZE. If the amount of storage required for a atomic counter buffer exceeds this limit, a program may fail to link. If is ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS, then the number of active atomic counter variables associated with the atomic counter buffer identified by is returned. If is ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTER_INDICES, then a list of the active atomic counter indices for the atomic counter buffer identified by is returned. The number of elements that will be written to is the value of ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS for . If is ATOMIC_COUNTER_BUFFER_REFERENCED_BY_VERTEX_SHADER, ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TESS_CONTROL_SHADER, UNIFORM_BLOCK_REFERENCED_BY_TESS_EVALUATION_SHADER, ATOMIC_COUNTER_BUFFER_REFERENCED_BY_GEOMETRY_SHADER, or ATOMIC_COUNTER_BUFFER_REFERENCED_BY_FRAGMENT_SHADER, then a boolean value indicating whether the atomic counter buffer identified by is referenced by the vertex, tessellation control, tessellation evaluation, geometry, or fragment programming stages of , respectively, is returned." Modify first sentence of last paragraph on p. 76, beginning with "Each active uniform, whether in a named..." Each active uniform, except for subroutine uniforms, whether in a the default block, in a named uniform block, or an atomic counter... Modify first sentence of the fourth paragraph on p. 77 beginning with "The name of an active..." The name of an active uniform, except for subroutine uniforms, may be querried... Replace the last paragraph on p. 77 beginning with "Each uniform variable..." Each active uniform variable, except subroutine uniforms, is broken down into one or more strings using the "." (dot) and "[]" operators, if necessary, to the point that it is legal to pass each string back into GetUniformIndices. Modify first sentence of first paragraph on p. 78 beginning with "Information about active uniforms..." Information about active uniforms, except for subroutine uniforms, can be... Replace the fourth paragraph on p. 78 beginning with "Each uniform variable..." Each active uniform variable, except subroutine uniforms, is broken down into one or more strings using the "." (dot) and "[]" operators, if necessary, to the point that it is legal to pass each string back into GetUniformIndices. Modify the last paragraph Add to Table 2.13, p. 81 Type Name Token Keyword Attrib Xfb --------------------------- ----------- ------ --- UNSIGNED_INT_ATOMIC_COUNTER atomic_uint Modify description of UNIFORM_OFFSET query in GetActiveUniformsiv, p. 82 If is UNIFORM_OFFSET, then an array of buffer offsets is returned. For uniforms in a named uniform block, the returned value will be its offset, in basic machine units, relative to the beginning of the uniform block in the buffer object data store. For atomic counter uniforms, the returned value will be its offset relative to the beginning of its active atomic counter buffer. For all other uniforms, an offset of -1 will be returned. If is UNIFORM_ARRAY_STRIDE, then an array of strides between array elements in buffer object storage is returned. For uniforms in named uniform blocks and for uniforms declared as atomic counters, the stride is the difference, in basic machine units, of the offsets of consecutive elements in an array, or zero for uniforms not declared as an array. For all other uniforms, a stride of -1 will be returned. Add prior to "Loading Uniform Values In The Default Uniform Block", p. 83 If is UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX, then an array identifying the active atomic counter buffer index of each of the uniforms specified by the corresponding array of is returned. For uniforms other than atomic counters, the returned buffer index is -1. The returned indices can be passed to GetActiveAtomicCounterBufferiv to query properties of the associated buffer, and not necessarily the binding point specified in the uniform declaration. Modify first sentence of first new paragraph on p. 83 beginning with "To load values into the uniform variables..." To load values into the uniform variables of the default uniform block of the active program object, except for subroutine uniforms and atomic counters, ..." Modify first sentence of the fifth paragraph on p. 84 beginning with "For all other uniform types..." For all other uniform types, except for subroutine uniforms and atomic counters, ... Add new unnumbered subsections at the end of the section, p. 90 Atomic Counter Buffers The values of atomic counters are backed by buffer object storage. The mechanisms for accessing individual atomic counters in a buffer object and connecting to an atomic counter are described in this section. There is a set of implementation-dependent maximums for the number of active atomic counter buffers referenced by each shader. If the number of atomic counter buffers referenced by any shader in the program exceeds its corresponding limit, the program will fail to link. The limits for vertex, tessellation control, tessellation evaluation, geometry, and fragment shaders can be obtained by calling GetIntegerv with pname values of MAX_VERTEX_ATOMIC_COUNTER_BUFFERS, MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS, MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS, MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS, or MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS, respectively. Additionally, there is an implementation-dependent limit on the sum of the number of active atomic counter buffers used by each shader of a program. If an atomic counter buffer is used by multiple shaders, each such use counts separately against this combined limit. The combined atomic counter buffer use limit can be obtained by calling GetIntegerv with a of MAX_COMBINED_ATOMIC_COUNTER_BUFFERS. Atomic Counter Buffer Object Storage Atomic counters stored in buffer objects are represented in memory as follows: * Members of type atomic_uint are extracted from a buffer object by reading a single uint-typed value at the specified offset. * Arrays of type atomic_uint are stored in memory by element order, with array element member zero at the lowest offset. The difference in offsets between each pair of elements in the array in basic machine units is referred to as the array stride, and is constant across the entire array. The stride can be queried by calling GetIntegerv with a of UNIFORM_ARRAY_STRIDE after a program is linked. Atomic Counter Buffer Bindings The value of an active atomic counter is extracted from or written to the data store of a buffer object bound to one of an array of atomic counter buffer binding points. The number of binding points can be queried by calling GetIntegerv with a of MAX_ATOMIC_COUNTER_BUFFER_BINDINGS. Regions of buffer objects are bound as storage for atomic counters by calling one of the commands BindBufferRange or BindBufferBase (see section 2.9.1) with set to ATOMIC_COUNTER_BUFFER. In addition to the general errors described in section 2.9.1, BindBufferBase and BindBufferRange will generate an INVALID_VALUE error if is greater than or equal to the value of MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, and BindBufferRange will generate an INVALID_VALUE error if is not a multiple of four. Each of a program's active atomic counter buffer bindings has a corresponding atomic counter buffer binding point. This binding point is established with the layout qualifier in the shader text, either explicitly or implicitly, as described in the Shading Language specification. When executing shaders that access atomic counters, each active atomic counter buffer must be populated with a buffer object with a size no smaller than the minimum required size for that buffer (the value of ATOMIC_COUNTER_BUFFER_DATA_SIZE). For binding points populated by BindBufferRange, the size in question is the value of the parameter. If any active atomic counter buffer is not backed by a sufficiently large buffer object, the results of shader execution are undefined, and may result in GL interruption or termination. Add to Section 2.11.11 Shader Execution, p. 102, inserting before Shader Inputs Atomic Counter Access Shaders have the ability to set and get atomic counters. The maximum number of atomic counters available to shaders are the values of the implementation dependent constants * MAX_VERTEX_ATOMIC_COUNTERS (for vertex shaders), * MAX_TESS_CONTROL_ATOMIC_COUNTERS (for tessellation control shaders), * MAX_TESS_EVALUATION_ATOMIC_COUNTERS (for tessellation evaluation shaders), * MAX_GEOMETRY_ATOMIC_COUNTERS (for geometry shaders), and * MAX_FRAGMENT_ATOMIC_COUNTERS (for fragment shaders). All active shaders combined cannot use more than the value of MAX_COMBINED_ATOMIC_COUNTERS atomic counters. If more than one pipeline stage accesses the same atomic counter, each such access counts separately against the MAX_COMBINED_ATOMIC_COUNTERS limit. Additions to Chapter 6 of the OpenGL 4.1 (Core Profile) Specification (State and State Requests) Add to the end of section 6.1.8 (Buffer Object Queries) To query which buffer objects are bound to the array of transform feedback binding points and will be used when transform feedback is active, call GetIntegeri\_v with set to TRANSFORM_FEEDBACK_BUFFER_BINDING. must be in the range zero to the value of MAX_TRANSFORM_FEEDBACK_BUFFERS minus one. The name of the buffer object bound to is returned in . If no buffer object is bound for , zero is returned in . The error INVALID_VALUE is generated if is greater than or equal to the value of MAX_TRANSFORM_FEEDBACK_BUFFERS. To query the starting offset or size of the range of each buffer object binding used for transform feedback, call GetInteger64i_v with set to TRANSFORM_FEEDBACK_BUFFER_START or TRANSFORM_FEEDBACK_BUFFER_SIZE respectively. must be in the range 0 to the value of MAX_TRANSFORM_FEEDBACK_BUFFERS minus one. If the parameter (starting offset or size) was not specified when the buffer object was bound (e.g. if bound with BindBufferBase), or if no buffer object is bound to , zero is returned. The error INVALID_VALUE is generated if is greater than or equal to the value of MAX_TRANSFORM_FEEDBACK_BUFFERS}. Add to Section 6.1.12, immediately before the description of IsProgramPipeline (p. 335) If is ACTIVE_ATOMIC_COUNTER_BUFFERS, the number of active atomic counter buffers used by is returned. Additions to Appendix A (Invariance) Add additional sentence to A.3 Invariance Rules, Rule 4 (p. 399) Invariance is relaxed for shaders with side effects (such as accessing atomic counters), see A.5, Atomic Counter Invariance. Add A.5 Atomic Counter Invariance When using a program containing atomic counters, the following invariance rules are intended to provide repeatability guarantees but within certain constraints. Rule 1 When a single shader type within a program accesses an atomic counter with only atomicCounterIncrement, any individual shader invocation is guaranteed to get a unique value returned. Corollary 1 - Also holds true with atomicCounterDecrement. Corollary 2 - This does not hold true for atomicCounter Corollary 3 - Repeatability is relaxed. While a unique value is returned to the shader, even given the same initial state vector and buffer contents, it is not guaranteed that the *SAME* unique value will be returned for each individual invocation of a shader (For example, on any single vertex, or any single fragment). It is wholly the shader writer's responsibility to respect this constraint. Rule 2 When two or more shader types within a program access an atomic counter with only atomicCounterIncrement, there is no repeatability of the ordering of operations between stages. For example, some number of vertices may be processed, then some number of fragments may be processed. Corollary 4 - This also holds true with atomicCounterDecrement and atomicCounter. Additions to Appendix D (Shared Objects and Multiple Contexts) Modify D.3 (Propagating State Changes) (add to list of bullets at the end of the section, p. 467) * Rendering commands that trigger shader invocations, where the shader performs built-in atomic counter functions. New State Add new table, labeled "Program Object State (cont.)" after Table 6.36, p. 377 Initial Get Value Type Get Command Value Description Sec. ----------------------- ---- ----------- ------- ------------------------ ----- ACTIVE_ATOMIC_COUNTER_BUFFERS Z+ GetProgramiv 0 Number of active atomic 2.11.7 counter buffers used by a program ATOMIC_COUNTER_BUFFER_BINDING nxZ+ GetActiveAtomic- - Binding point associated 2.11.7 CounterBufferiv with an active atomic counter buffer ATOMIC_COUNTER_BUFFER_DATA_SIZE nxZ+ GetActiveAtomic- - Minimum size required by 2.11.7 CounterBufferiv an active atomic counter buffer ATOMIC_COUNTER_BUFFER_ACTIVE_ nxZ+ GetActiveAtomic- - Number of active atomic 2.11.7 ATOMIC_COUNTERS CounterBufferiv counters in an active atomic counter buffer ATOMIC_COUNTER_BUFFER_ACTIVE_ mxnxZ+ GetActiveAtomic- - List of active atomic 2.11.7 ATOMIC_COUNTER_INDICES CounterBufferiv counters in an active atomic counter buffer ATOMIC_COUNTER_BUFFER_ nxB GetActiveAtomic- FALSE Active atomic counter 2.11.7 REFERENCED_BY_VERTEX CounterBufferiv buffer has a counter used SHADER by vertex shaders ATOMIC_COUNTER_BUFFER_ nxB GetActiveAtomic- FALSE Active atomic counter 2.11.7 REFERENCED_BY_TESS_CONTROL CounterBufferiv buffer has a counter used SHADER by tess. control shaders ATOMIC_COUNTER_BUFFER_ nxB GetActiveAtomic- FALSE Active atomic counter 2.11.7 REFERENCED_BY_TESS_EVALUTION CounterBufferiv buffer has a counter used SHADER by tess. evaluation shaders ATOMIC_COUNTER_BUFFER_ nxB GetActiveAtomic- FALSE Active atomic counter 2.11.7 REFERENCED_BY_GEOMETRY CounterBufferiv buffer has a counter used SHADER by geometry shaders ATOMIC_COUNTER_BUFFER_ nxB GetActiveAtomic- FALSE Active atomic counter 2.11.7 REFERENCED_BY_FRAGMENT CounterBufferiv buffer has a counter used SHADER by fragment shaders UNIFORM_ATOMIC_COUNTER_BUFFER_ nxZ+ GetActive- - Active atomic counter 2.11.7 INDEX Uniformsiv buffer associated with an active uniform Add new table, labeled "Atomic Counter State", after Table 6.39, p. 380 Initial Get Value Type Get Command Value Description Sec. ----------------------- ---- ----------- ------- ------------------------ ----- ATOMIC_COUNTER_BUFFER_BINDING Z+ GetIntegerv 0 Current value of generic 2.9.9 atomic counter buffer binding ATOMIC_COUNTER_BUFFER_BINDING n*Z+ GetIntegeri_v 0 Buffer object bound 2.9.9 to each atomic counter buffer binding point ATOMIC_COUNTER_BUFFER_START n*Z+ GetInteger64i_v 0 Start offset of 2.9.9 binding range for each atomic counter buffer ATOMIC_COUNTER_BUFFER_SIZE n*Z+ GetInteger64i_v 0 Size of binding range for 2.9.9 each atomic counter buffer New Implementation Dependent State Add to Table 6.46, Implementation Dependent Vertex Shader Limits, p. 387: Get Value Type Get Command Minimum Value Description Sec. ----------------------- ---- ----------- ------------- ------------------------- ----- MAX_VERTEX_ATOMIC_COUNTER_BUFFERS Z+ GetIntegerv 0 Number of atomic counter 2.11.7 buffers accessed by a vertex shader MAX_VERTEX_ATOMIC_COUNTERS Z+ GetIntegerv 0 Number of atomic counters 2.11.11 accessed by a vertex shader Add to Table 6.47, Implementation Dependent Tesselation Shader Limits, p. 388: Get Value Type Get Command Minimum Value Description Sec. ----------------------- ---- ----------- ------------- ------------------------- ----- MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS Z+ GetIntegerv 0 Number of atomic counter 2.11.7 buffers accessed by a tesselation control shader MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS Z+ GetIntegerv 0 Number of atomic counter 2.11.7 buffers accessed by a tesselation evaluation shader MAX_TESS_CONTROL_ATOMIC_COUNTERS Z+ GetIntegerv 0 Number of atomic counters 2.11.11 accessed by a tesselation control shader MAX_TESS_EVALUATION_ATOMIC_COUNTERS Z+ GetIntegerv 0 Number of atomic counters 2.11.11 accessed by a tesselation evaluation shader Add to Table 6.48, Implementation Dependent Geometry Shader Limits, p. 389: Get Value Type Get Command Minimum Value Description Sec. ----------------------- ---- ----------- ------------- ------------------------- ----- MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS Z+ GetIntegerv 0 Number of atomic counter 2.11.7 buffers accessed by a geometry shader MAX_GEOMETRY_ATOMIC_COUNTERS Z+ GetIntegerv 0 Number of atomic counters 2.11.11 accessed by a geometry shader Add to Table 6.49, Implementation Dependent Fragment Shader Limits, p. 390: Get Value Type Get Command Minimum Value Description Sec. ----------------------- ---- ----------- ------------- ------------------------- ----- MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS Z+ GetIntegerv 1 Number of atomic counter 2.11.7 buffers accessed by a fragment shader MAX_FRAGMENT_ATOMIC_COUNTERS Z+ GetIntegerv 8 Number of atomic counters 2.11.11 accessed by a fragment shader Add to Table 6.50 Implementation Dependent Aggregate Shader Limits, p. 391: Get Value Type Get Command Minimum Value Description Sec. ----------------------- ---- ----------- ------------- ------------------------- ----- MAX_ATOMIC_COUNTER_BUFFER_BINDINGS Z+ GetIntegerv 1 Max. number of atomic 2.9.9 counter buffer bindings MAX_ATOMIC_COUNTER_BUFFER_SIZE Z+ GetIntegerv 32 machine units of an atomic counter buffer MAX_COMBINED_ATOMIC_COUNTER_BUFFERS Z+ GetIntegerv 1 Max. number of atomic 2.11.7 counter buffers per program MAX_COMBINED_ATOMIC_COUNTERS Z+ GetIntegerv 8 Max. number of atomic 2.11.11 counter uniforms per program Additions to the OpenGL Shading Langauge 4.10.6 Specification Including the following line in a shader can be used to control the language features described in the extension: #extension GL_ARB_shader_atomic_counters : where is as specified in section 3.3. A new preprocessor #define is added to the OpenGL Shading Language: #define GL_ARB_shader_atomic_counters 1 Additions to Chapter 3 of the OpenGL Shading Language 4.10.6 Specification Add to 3.6 Keywords (pp. 13-15) atomic_uint Additions to Chapter 4 of the OpenGL Shading Language 4.10.6 Specification Add to Section 4.1 Basic Types Unsigned Integer Counter Types (opaque) Type Meaning atomic_uint a handle for accessing an unsigned integer atomic counter Insert Section 4.1.8 Atomic Counters (existing 4.1.8 becomes 4.1.9, and so on) 4.1.8 Atomic Counters Atomic Counter types (e.g. atomic_uint) are effectively opaque handles to counters. They are used with the built-in atomic counter functions (described in section 8.10 "Atomic Counter Functions") to specify which counter to access. They can only be declared as function parameters or uniform-qualified global variables. Except for array indexing, structure field selection, and parenthesis, counters are not allowed to be operands in expressions. Counters aggregated into arrays within a shader (using square brackets []) can only be indexed with dynamically uniform integral expressions, otherwise results are undefined. Counters cannot be treated as l-values; hence cannot be used as out or inout function parameters, nor can they be assigned into. Modify last sentence of first paragraph of section 4.3.5, p. 36 beginning with "Sampler types cannot..." Sampler types and atomic counter types cannot..." Insert Section 4.3.6 Atomic Counters. (Existing 4.3.6 becomes 4.3.7, and so on) 4.3.6 Uniform The uniform qualifier is used to declare global opaque handles (to counters) where the handles are the same across the entire primitive being processed. All uniform variables are read-only and are initialized at link time. It is an error to write to a uniform-qualified variable. For example, layout( binding=2, offset=0 ) uniform atomic_uint a; will establish that the opaque handle to the atomic counter "a" will be bound to atomic counter buffer binding 2 at offset 0. There is an implementation dependent limit to the number of uniforms that can be used for each type of shader and if this is exceeded it will cause a compile-time or link-time error. Uniform variables that are declared but not used may or may not count against this limit. If multiple shaders are linked together, then they will share a single global uniform name space, including within the language as well as across languages. Hence, the type of uniform variables with the same name must match across all shaders that are linked into a single program. It is legal for some shaders to provide a layout qualifier for a uniform variable of the same name, while another shader does not provide a layout qualifier for a uniform variable of the same name, but if provided, all provided layout qualifiers must be equal for a uniform variable of the same name, and if not provided, all implicitly provided layout qualifiers must be equal for a uniform variable of the same name. Add Section 4.3.8.4 Uniform Layout Qualifiers Layout qualifiers can be used on uniform declarations. The uniform qualifier identifiers for uniforms are layout-qualifier-id binding = integer-constant offset = integer-constant For example, layout(binding = 2, offset = 4) uniform atomic_uint foo; will establish that the atomic counter foo has a binding to buffer binding point 2 and an offset of 4 basic machine units in that buffer. The offset will be post-incremented by the size of the uniform (for atomic_uint, 4 basic machine units). A subsequent uniform declaration will inherit the binding, and offset (perhaps post-incremented). For example, a subsequent declaration of, uniform atomic_uint bar; will establish that the atomic counter bar has a binding to buffer binding point 2 and an offset of 8 basic machine units in that buffer. The offset will be post-incremented by the size of the uniform (again, for atomic_uint, 4 basic machine units). If the limit on the maximum number of bindings is exceeded, or if the limit of the maximum number of counters (either per shader type or combined) is exceeded, it will be a link error. It is a compile error to bind an atomic counter with a value greater than or equal to gl_MaxAtomicCounterBindings. Add Section 4.3.8.3 Uniform Layout Qualifiers prior to existing 4.3.8.3 Uniform Block Layout Qualifiers, and renumber subsequent sections Layout qualifiers can be used on uniform declarations. The layout qualifiers identifiers for uniforms are layout-qualifier-id binding = integer-constant offset = integer-constant Uniform layout qualifiers can be declared for global scope or on a single uniform declaration. Default layouts are established at global scope for uniforms as layout (layout-qualifier-id-list) uniform; When this is done, the previous default qualification is first inherited and then overridden as per the override rules listed below. The result becomes the new default qualification scoped to subsequent uniform block definitions. The initial state of compiliation is as if the following were declared: layout(binding=0, offset=0) uniform; Explicitly declaring this in a shader will return defaults back to their initial state. Uniforms can be declared with optional layout qualifiers. As with global layout declarations, uniform layout qualification first inherits from the current default qualification and then overrides it. When multiple arguments are listed in a layout declaration, the affect will be the same as if they were declared one at a time, in order from left to right, each in turn inheriting from and overriding the result from the previous qualification. For each uniform element, the then current default layout qualifiers will be applied, together with any prior post-increments of offset, if applicable, then the offset will be post-incremented by the size of the uniform, in basic machine units. Uniforms may share the same binding, but if a binding is shared, each offset must be explicitly or implicitly unique. For example a valid uniform declarations: layout(binding=3, offset=4) uniform; uniform atomic_uint thunderhead; // offset = 4 uniform atomic_uint stratogirl; // offset = 8 layout(binding=3) uniform atomic_uint metalman; // binding matches, // offset = 12 layout(offset=20) uniform atomic_uint dynaguy; // offset = 20 uniform atomic_uint splashdown; // offset = 24 Example of an invalid uniform declarations; layout(binding=1, offset=0) batman; // OK layout(binding=2, offset=0) robin; // OK layout(binding=1, offset=0) catwoman; // error, offsets // must not be shared // between batman and // catwoman Additions to Chapter 7 of the OpenGL Shading Language 4.10.6 Specification (Built-in Variables) Add to Section 7.4, Built-In Constants const int gl_MaxVertexAtomicCounters = 0; // minimum maximum const int gl_MaxTessControlAtomicCounters = 0; // minimum maximum const int gl_MaxTessEvaluationAtomicCounters = 0; // minimum maximum const int gl_MaxGeometryAtomicCounters = 0; // minimum maximum const int gl_MaxFragmentAtomicCounters = 8; // minimum maximum const int gl_MaxCombinedAtomicCounters = 8; // minimum maximum const int gl_MaxAtomicCounterBindings = 1; // minimum maximum Additions to Chapter 8 of the OpenGL Shading Language 1.50 Specification (Built-in Functions) Add Section 8.10 Atomic Counter Functions (existing 8.10 becomes 8.11, and so on) 8.10 Atomic Counter Functions Atomic counter functions have exclusive access to any single counter, perform an atomic operation, then release exclusive access to that counter, as-if a single step. Any other atomic counter function may access that single counter only after any earlier atomic operation is completed. The value returned by an atomic counter function is the value of an atomic counter, which may be: returned and incremented in an atomic operation, or decremented and returned in an atomic operation, or simply returned. The underlying counter is a 32-bit unsigned integer. Increments and decrements at the limit of the range will wrap to [0, 2^32-1]. Syntax Description uint atomicCounterIncrement Increments atomically, returning ( atomic_uint counter ); the value prior to the increment operation. uint atomicCounterDecrement Decrements atomically, returning ( atomic_uint counter ); the value after the decrement operation. uint atomicCounter Returns the value of . ( atomic_uint counter ); Sample Code layout( binding=2) uniform atomic_uint a; layout( binding=2, offset=4 ) uniform atomic_uint b; layout( binding=5, offset=0 ) uniform atomic_uint c; // ... uint foo = atomicCounterIncrement( a ); // get the counter value, then increment the counter // atomic operation uint bar = atomicCounterDecrement( b ); // decrement the counter value, then get the counter // atomic operation uint baz = atomicCounter( c ); // get the counter value // atomic operation Issues 1 - Do we need an indirection table between the counters and the shaders? (Similar to Samplers? VertexAttribBinding? Uniform blocks?) Yes. This draft introduces opaque counters similar to samplers. However, there is no Uniform-like API means of setting them to a texture unit or attribute-like API of binding them to a location. Instead, we have uniforms, which are a storage qualifier at global scope, and which use layout qualifiers to bind them to buffer binding points. A GetActiveUniforms API is used to retrieve the names of the counters, and their bindings, and other useful information. 2 - What shader stages are these available in? Resolved. All stages. 3 - Can the counters be operated on in the shading language? Resolved: Not directly. But indirectly, probably not in any meaningful way. But there are no restrictions placed on the values once they are returned to the shader. 4 - Where's issue 4? Resolved. It's here. 5 - Can a single shader both increment and decrement an individual atomic counter? Resolved: Yes, with caveats. In order to provide a global unique offset, a counter must *either* be incremented or decremented by a shader. The best way to think of this is that these are UNORDERED increments and decrements. However, there may be uses for these atomic counters other than providing unique offsets. We provide mechanism, not policy. Shader coding conventions can provide policy - there's little reason for the compiler to be involved in enforcing. 6 - Can multiple shaders in a program both increment and decrement an individual atomic counter? Resolved. Yes, with the same caveats as above. 7 - Is there a maximum maximum number of counters? Resolved. No, implementations are free to support arbitrarily many counters. Implementations may set their own limits, though there are specified minimum limits. 8 - Can a counter be queried, but not incremented/decremented in the shader? Resolved: Yes. (It's an increment of zero. Or a decrement of zero.) Note that using a get without an increment or decrement will return a value that is *not* unique. Again, we provide mechanism, not policy. 9 - Can a counter be incremented/decremented by an arbitrary amount? Resolved: No. Only by 1. (Or 0.) 10 - Should append counters wrap on zero and overflow? Resolved: Wrap. [0,2^32-1] 11 - What piece of state owns the atomic counters? Resolved: There is no context state, they must be backed by buffer objects. 12 - Can the atomic counters be shared between contexts? Resolved: Not directly, but they may be shared indirectly by sharing the buffer objects that back them. 13 - Should we be able to write atomic counters to a buffer object? Resolved. Yes. (Note that buffer objects can be shared. The result of updating atomic counters in multiple contexts backed with the same buffer object is undefined.) 14 - If indexing an array of atomic_uints, can the index used diverge in a SIMD implementation? Resolved. No. They must be dynamically uniform, similar to samplers. 15 - Should we provide "append buffer" functionality? Resolved: Yes, but by providing access to atomic counters. This provides the mechanism to do "append buffer" functionality, and more. 16 - What should this extension be called? Resolved: ARB_shader_atomic_counters. It's primarily a shader extension, and it provides atomic_counters. 17 - What happens to shared buffer objects that are updated in more than one context by data-setting commands, including the built-in atomic counter functions? Resolved: They should follow the same rules as other shared buffer objects. (That is, care must be taken when updating atomic counters in one context and using them in another context.) Further, the atomic built-in functions are atomic in a single context, but there is no guarantee that they are atomic across contexts. 18 - Should there be one buffer binding for all counters, or a buffer binding per counter. Resolved. There should be a buffer binding (and offset) per counter. Shaders may store multiple atomic counters in a single buffer binding. 19 - What about simultaneous use of buffer object at two binding points, where one is an atomic counter binding point? Resolved. We are going to be conservative and make such use undefined. 20 - Does atomic_uint type add any value? Resolved. Yes. For a single program text, the opaque atomic_uint is just syntactic sugar. However, for multiple shaders bound to a shader target, only one shader must contain the locations. This would permit an implementation to do fast relinking if a single shader is attached to an existing shader. (And display lists are just fine for optimizing texture loads. [insert silly smiley face]) Also, when we do add api (not yet added) to query active atomic_uints in a shader, this provides additional benefits. 21 - Do we need api to query the atomic counter? Resolved. Earlier drafts had a traditional indexed get, which would be useful for debugging but not high performance. An alternative would be to add a query object to do asynchronos queries. But note, that when these counters are backed by buffer objects, all the GetBufferSubData and/or MapBuffer just works. This draft simply nukes the get. (It is trivial to put it back in with a caveat.) The existing buffer api should be used for high performance client side (cpu) access to atomic counters. 22 - Does AtomicCounter reset to zero: The context default counter state? The value in a buffer object bound to a counter? Both? Resolved. THERE IS NO DEFAULT CONTEXT STATE, only the buffer object bound, if any, is set. 23 - Does a BufferData to a buffer bound to counter set the value of: The buffer object? (Obviously) The context default counter state bound that that buffer? Resolved. THERE IS NO DEFAULT CONTEXT STATE. 24 - Do we want an error (or undefined behavior) that says you can't draw while a mapped buffer is bound to one of these counters? Resolved. Undefined. 25 - Is a atomic_uint an "in" or a "uniform"? Resolved. "atomic_uint" variables are declared as uniforms at global scope. 26 - Can the active atomic counters for one program be stored in more than one buffer object? Resolved. Yes. 27 - Can atomic counters be grouped into blocks similar to uniform blocks? Resolved. No. However, layout qualifiers can be used in individual declarations to identify a specific buffer binding point and offset to use for the counter. 28 - What API should be used to query information about atomic counters? Resolved. GetActiveUniformsiv. Apart from the common type and count queries, UNIFORM_OFFSET can be used to query the offset of an atomic counter, UNIFORM_ARRAY_STRIDE can be used to query the stride in memory of an array of atomic counters (even though it's always four bytes), and UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX can be used to query the index of the active atomic counter buffer associated with the uniform. No GetActiveUniformsiv query is provided to retrieve the binding point associated with an atomic counter uniform. It may be obtained indirectly by UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX and then using GetAtomicCounterBufferiv to query the ATOMIC_COUNTER_BUFFER_BINDING for the returned index. 29 - What API should we provide to query information about buffer object storage needed to back atomic counters? Unresolved. We will provide an API for querying information about "active atomic counter buffers" similar to the API we provide for querying active uniform blocks. Each set of active atomic counter uniforms sharing a single binding point corresponds to an active atomic counter buffer. An application can query the number of active atomic counter buffers via GetProgram. If there are active atomic counter buffers, it can pass the values 0..-1 to the command GetAtomicCounterBufferiv to query properties of each buffer. Consider the following set of active atomic counter uniform declarations in three different shader types in a program: [in vertex] layout(binding = 0, offset = 0) uniform atomic_uint batman; layout(binding = 3, offset = 4) uniform atomic_uint robin; [in geometry] layout(binding = 0, offset = 4) uniform atomic_uint joker; layout(binding = 6, offset = 124) uniform atomic_uint riddler; [in fragment] layout(binding = 7, offset = 0) uniform atomic_uint penguin; In this example, there are four active atomic counter buffers. For the purposes of the GetActiveAtomicCounterBufferiv query, these will be assigned indices 0, 1, 2, 3. If the active atomic counter buffers are sorted by binding point, the atomic counter buffer binding point numbers returned by calling GetActiveAtomicCounterBufferiv with a of ATOMIC_COUNTER_BUFFER_BINDING, will be 0, 3, 6, and 7, respectively. 30 - The function atomicCounterIncrement() returns the value of the counter prior to incrementing while atomicCounterDecrement() returns the value of the counter *after* decrementing. Is this intentional? Resolved. Yes. One of the intended uses of this programming model is to be able to atomically add or remove records to an array stored in a buffer (via ARB_shader_image_load_store). In this model, we use the atomic counter to indicate the number of records stored in the buffer and expect the value to be initialized to zero. When the first record is added, it gets an index of zero and increments the counter to one. If a later operation wants to remove a record from the end of a buffer with an associated counter value , we would want to decrement to counter to -1, but also return the decremented index of -1, which was the index of the last record in the buffer prior to the decrement. 31 - What alignment requirements apply to the and parameters of BindBufferRange when binding atomic counter buffers? Resolved. must be a multiple of four. has no required alignment. However, if is not four-byte aligned, it will not possible to store an atomic counter in the last few bytes of the bound range since the offset of all atomic counters must also be a multiple of four. Revision History Revision 1, wwlk, 2009-09-08 - Working Draft Revision 2, wwlk, 2009-09-08 - updates from feedback Revision 3, wwlk, 2009-09-09 - (9/9/9, yeah yeah yeah) - updates from feedback Revision 4, wwlk, 2009-09-15 - updates from walkthrough - minor typo update (2.9.10 should be 2.9.9) - add extension enables and defines to shader spec - correct function names (add EXT suffix) - rename extension Revision 5, wwlk, 2009-09-15 - Clarify buffer objects - Clarify undersized buffer objects Revision 6, wwlk, 2009-09-16 - Clarify alignment restrictions for buffer object - Update built-in function names and descriptions - Add issue about number of binding points Revision 7, wwlk, 2010-10-17 - Add opaque ucounter - add buffer binding and offset per counter Revision 8, wwlk, 2010-10-28 - make it clear that these use the indexed binding api (ala transform feedback) - remove get (bug 5839, issue 2 in bug, issue 21 in this extension) - remove fragment restriction (bug 5839, issue 5 in bug, issue 2 in this extension) - add issue 4 - add other issues from bug 5839 - Some clarifications from bug 6975 Revision 9, wwlk, 2010-11-30 - added new global qualifier, uniform - clarified no default context state - clarified the action of BindBufferRange - corrected alignment and sizing restrictions - Still to be done - GetActiveUniforms API! Revision 10, wwlk, 2010-12-02 - GetActiveUniforms API - change ucounter -> atomic_uint Revision 11, wwlk, 2010-12-02 - Removed unnecessary AtomicCounterEXT API. (use buffer API) Revision 12, wwlk, 2010-12-03 - Trivial typos Revision 13, wwlk, 2010-12-03 - More trivial typos Revision 14, wwlk, 2010-12-03 - Still more trivial typos Revision 15, wwlk, 2010-12-09 - Still more trivial typos - Clarifications - Additional uniform API - next revision (the obvious additions, but unfortunately extensive. Proofing now.) Revision 16, johnk, 2010-12-17 - Change MAX_ATOMIC_COUNTERS to gl_MaxAtomicCounterBindingsEXT (is that correct?) - Move that statement from the uniform section to the qualifier section. - added integer constants to the layout qualifier grammar - minor grammar and consistency changes going into 4.2 core. Revision 17, Jon Leech, 2010-12-19 - Change extension name to ARB instead of EXT. Remove _EXT suffixes on API since this extension is backwards-compatibility for a core GL 4.2 feature. Probably should remove suffixes on GLSL interface as well. - Fix version number for API spec in section headings. Revision 18, Jon Leech, 2011-01-05 - Fix typos from Bug 7202 Revision 19, wwlk, 2011-04-05 - Uniform API - large rework - Clarify limits - Clarify layouts, binding rules, offset rules - Clarify named uniform blocks - Clarify unnamed uniform blocks Revision 20, wwlk, 2011-04-08 - Clarify named uniform blocks with examples - Make explicit the matching rules for layout (explicit or implicit layout must match) - Added issue 29, do we need both un-named uniform blocks and uniform blocks? - Added issue 30, should the un-named uniform blocks be un-named "", or should they be implicitly named (example, uniform3 for binding to 3) Revision 21, wwlk, 2011-04-08 - Minor change to invalid uniform block example Revision 22, wwlk, 2011-05-05 - Major change uniforms (immutable) Revision 23, wwlk, 2011-05-05 - Fixed hellacious paragraph, related to bug 7458 "Each active uniform variable ... "." (dot) and "[]" ..." Revision 24, Jon Leech, 2011-05-08 - Minor formatting/typo cleanup. Fix name of query in state tables. Remove EXT suffixes from shader constant and function names. Revision 25, pbrown, 2011-06-18 - Add missing entries in the lists of new functions and tokens. - Assigned enumerant values for new tokens. - Minor language clarifications and typo fixes. - Clarify the two different numbering spaces for buffers used for atomic counters. The set of binding points actively referenced by a particular program are called "active atomic counter buffers"; the set of binding points in the context to which buffers are attached query are called "atomic counter bindings" or "binding points". Related APIs and tokens use "buffer" for the former and "binding" for the latter (bug 7723). - Add GetActiveUniformsiv support for atomic counters, allowing the use of UNIFORM_OFFSET and UNIFORM_ARRAY_STRIDE, and adding the query UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX to query the associated active atomic counter buffer. - Restructure the atomic counter buffer binding section to more closely match existing uniform block language; clarify alignment and buffer size requirements (bug 7722). - Remove explicit language about a minimum of 8 atomic counter buffers; already covered by existing queries and state table entries (bug 7722). - Add GetProgram language for ACTIVE_ATOMIC_COUNTER_BUFFERS. - Add missing state table entries for program object state and implementation limits on atomic counter buffer sizes and the combined active buffer count (bug 7722). - Clarify that we intended the non-orthogonality where the increment function returns a value prior to incrementing while the decrement function returns a value after decrementing (bug 7722). - Add a few issues and clarify/update some existing ones. Revision 26, pbrown, 2011-06-20 - Add missing enum assignment for MAX_ATOMIC_COUNTER_BUFFER_BINDINGS. Revision 27, pbrown, 2011-06-23 - Set a minimum value for MAX_ATOMIC_COUNTER_BUFFER_SIZE (bug 7743). - Fix typo in state table. Revision 28, pbrown, 2011-07-27 - Clarify that ATOMIC_COUNTER_BUFFER_ACTIVE_ATOMIC_COUNTERS queries the number of atomic counter variables (bug 7834). - Fix tokens MAX_*_ATOMIC_COUNTER_BUFFERS in the state table (bug 7834). - Fix a couple typos. Revision 29, Jon Leech, 2011-08-05 - Change minimum MAX_ATOMIC_COUNTER_BUFFER_SIZE value to 32 (bug 7855). Revision 30, Jon Leech, 2012-04-12 - Add description of atomic buffer object binding queries in section 6.1.8. Correct typo for GetAtomicCounterBufferiv in state table entries. Revision 31, Jon Leech, 2012-07-30 - Correct typo ATOMIC_COUNTER_ARRAY_STRIDE -> UNIFORM_ARRAY_STRIDE (bug 9346).