Name

    ARB_shader_atomic_counter_ops

Name Strings

    GL_ARB_shader_atomic_counter_ops

Contact

    Daniel Rakos (daniel.rakos 'at' amd.com)

Contributors

    Daniel Rakos, AMD
    Graham Sellers, AMD
    Piers Daniell, NVIDIA

Notice

    Copyright (c) 2015 The Khronos Group Inc. Copyright terms at
        http://www.khronos.org/registry/speccopyright.html

Status

    Complete. Approved by the ARB on June 26, 2015.
    Ratified by the Khronos Board of Promoters on August 7, 2015.

Version

    Last Modified Date:         06/11/2015
    Author Revision:            6

Number

    ARB Extension #182

Dependencies

    This extension is written against version 4.50 of the OpenGL Shading
    Language Specification.

    OpenGL 4.2 or ARB_shader_atomic_counters is required.


Overview

    The ARB_shader_atomic_counters extension introduced atomic counters, but
    it limits list of potential operations that can be performed on them to
    increment, decrement, and query. This extension extends the list of GLSL
    built-in functions that can operate on atomic counters. The list of new
    operations include:

      * Addition and subtraction
      * Minimum and maximum
      * Bitwise operators (AND, OR, XOR, etc.)
      * Exchange, and compare and exchange operators


New Procedures and Functions

    None.


New Tokens

    None.


Modifications to the OpenGL Shading Language Specification, Version 4.50

Additions to Chapter 8 of the OpenGL Shading Language Specification
(Built-in Functions)

    Modify Section 8.10, Atomic-Counter Functions

    (remove second paragraph on p. 173 starting with "The value returned...")

    (modify third paragraph on p. 173)

    The underlying counter is a 32-bit unsigned integer. The result of
    operations will wrap to [0, 2^32-1].

    (add to the table of atomic counter built-in functions on p. 173)

    +-------------------------------------+------------------------------------------------------------------+
    | Syntax                              | Description                                                      |
    +-------------------------------------+------------------------------------------------------------------+
    | uint atomicCounterAddARB(           | Atomically                                                       |
    |     atomic_uint c,                  |   1. adds the value of <data> to the counter for c, and          |
    |     uint data)                      |   2. returns its value prior to the operation.                   |
    |                                     | These two steps are done atomically with respect to the atomic   |
    |                                     | counter functions in this table.                                 |
    +-------------------------------------+------------------------------------------------------------------+
    | uint atomicCounterSubtractARB(      | Atomically                                                       |
    |     atomic_uint c,                  |   1. subtracts the value of <data> from the counter for c, and   |
    |     uint data)                      |   2. returns its value prior to the operation.                   |
    |                                     | These two steps are done atomically with respect to the atomic   |
    |                                     | counter functions in this table.                                 |
    +-------------------------------------+------------------------------------------------------------------+
    | uint atomicCounterMinARB(           | Atomically                                                       |
    |     atomic_uint c,                  |   1. sets the counter for c to the minimum of the value of the   |
    |     uint data)                      |      counter and the value of <data>, and                        |
    |                                     |   2. returns the value prior to the operation.                   |
    |                                     | These two steps are done atomically with respect to the atomic   |
    |                                     | counter functions in this table.                                 |
    +-------------------------------------+------------------------------------------------------------------+
    | uint atomicCounterMaxARB(           | Atomically                                                       |
    |     atomic_uint c,                  |   1. sets the counter for c to the maximum of the value of the   |
    |     uint data)                      |      counter and the value of <data>, and                        |
    |                                     |   2. returns the value prior to the operation.                   |
    |                                     | These two steps are done atomically with respect to the atomic   |
    |                                     | counter functions in this table.                                 |
    +-------------------------------------+------------------------------------------------------------------+
    | uint atomicCounterAndARB(           | Atomically                                                       |
    |     atomic_uint c,                  |   1. sets the counter for c to the result of the bitwise AND of  |
    |     uint data)                      |      the value of the counter and the value of <data>, and       |
    |                                     |   2. returns the value prior to the operation.                   |
    |                                     | These two steps are done atomically with respect to the atomic   |
    |                                     | counter functions in this table.                                 |
    +-------------------------------------+------------------------------------------------------------------+
    | uint atomicCounterOrARB(            | Atomically                                                       |
    |     atomic_uint c,                  |   1. sets the counter for c to the result of the bitwise OR of   |
    |     uint data)                      |      the value of the counter and the value of <data>, and       |
    |                                     |   2. returns the value prior to the operation.                   |
    |                                     | These two steps are done atomically with respect to the atomic   |
    |                                     | counter functions in this table.                                 |
    +-------------------------------------+------------------------------------------------------------------+
    | uint atomicCounterXorARB(           | Atomically                                                       |
    |     atomic_uint c,                  |   1. sets the counter for c to the result of the bitwise XOR of  |
    |     uint data)                      |      the value of the counter and the value of <data>, and       |
    |                                     |   2. returns the value prior to the operation.                   |
    |                                     | These two steps are done atomically with respect to the atomic   |
    |                                     | counter functions in this table.                                 |
    +-------------------------------------+------------------------------------------------------------------+
    | uint atomicCounterExchangeARB(      | Atomically                                                       |
    |     atomic_uint c,                  |   1. sets the counter value for c to the value of <data>, and    |
    |     uint data)                      |   2. returns its value prior to the operation.                   |
    |                                     | These two steps are done atomically with respect to the atomic   |
    |                                     | counter functions in this table.                                 |
    +-------------------------------------+------------------------------------------------------------------+
    | uint atomicCounterCompSwapARB(      | Atomically                                                       |
    |     atomic_uint c,                  |   1. compares the value of <compare> and the counter value for c,|
    |     uint compare,                   |   2. if the values are equal, sets the counter value for c to    |
    |     uint data)                      |      the value of <data>, and                                    |
    |                                     |   3. returns its value prior to the operation.                   |
    |                                     | These three steps are done atomically with respect to the atomic |
    |                                     | counter functions in this table.                                 |
    +-------------------------------------+------------------------------------------------------------------+


Errors

    None.

New State

    None.

New Implementation Dependent State

    None.

Usage Examples

    Example 1: Appending variable length records to a buffer using a compute shader

        // Here we use atomicCounterAdd to ensure that we "allocate" a contiguous list of
        // elements in the buffer.
        // Using atomicCounterIncrement cannot mimic this behavior as there is no guarantee
        // that subsequent calls to atomicCounterIncrement return subsequent counter values.

        layout(binding=0, offset=0) uniform atomic_uint vlrCounter;
        layout(binding=0, r32ui) uniform imageBuffer vlrBuffer;

        void main()
        {
            uint data[...] = ...;
            uint recordLength = ...;

            uint recordStart = atomicCounterAddARB(vlrCounter, recordLength);

            for (uint i = 0; i < recordLength; ++i)
            {
                imageStore(vlrBuffer, recordStart + i, data[i]);
            }
        }

Issues

    (1) What additional operations should this extension introduce?

      RESOLVED: The following new operations are generally supported by
      target hardware:
        * Addition and subtraction
        * Minimum and maximum
        * Bitwise operators (AND, OR, XOR, etc.)
        * Exchange, and compare and exchange operators

    (2) How the functionality in this extension is different than that
        introduced by AMD_shader_atomic_counter_ops?

      RESOLVED: In addition to the operations introduced by this extension
      AMD_shader_atomic_counter_ops also adds support for wrapped increment,
      wrapped decrement, reverse subtract, and a special masked-or operation.
      Also, the semantics of the subtract operation is different between this
      and the AMD extension.

    (3) Should the new decrement with wrap and subtract operators match the
        behavior of the existing decrement operator and return the post-
        operation value of the counter?

      RESOLVED: Yes, for consistency with the existing functionality.

    (4) Most of the new operations introduced by this extension are already
        supported on load/store images and shader storage buffers. What benefit
        the application developer could get from using this extension?

      DISCUSSION: Atomic counter operations can have different performance
      characteristics than load/store images or shader storage buffers. It is
      expected that implementations can do atomic counter operations faster.

      RESOLVED: It enables existing operations for atomic counters and also
      adds completely new operations that are not available for load/store
      images and shader storage buffers.

    (5) Should the new subtract operator match the behavior of the existing
        decrement operator and return the post-operation value of the counter?

      RESOLVED: No, it returns the value of the counter prior to the operation,
      just like other atomic counter operations except decrement.

Revision History

    Rev.    Date    Author    Changes
    ----  --------  --------  -------------------------------------------------
      6   06/11/15  drakos    Updated resolution of issue (2) and (5) based on
                              the previous change.
      5   05/28/15  pdaniell  Modify the return semantics of
                              atomicCounterSubtractARB to return the result
                              prior to the operation.
      4   05/08/15  drakos    Added ARB suffixes to the built-in functions.
      3   03/18/15  drakos    Removed reverse subtract.
      2   03/17/15  drakos    Removed wrapped increment, wrapped decrement, and
                              masked-or operations. Also resolved outstanding
                              issues.
      1   02/03/15  drakos    Draft based on AMD_shader_atomic_counter_ops.
                              Rebased language for GLSL 4.50.
