Name

    ARB_multi_bind

Name Strings

    GL_ARB_multi_bind

Contact

    Pat Brown, NVIDIA Corporation (pbrown 'at' nvidia.com)

Contributors

    Jeff Bolz, NVIDIA
    Frank Chen, Qualcomm
    Piers Daniell, NVIDIA
    Daniel Koch, NVIDIA
    Jon Leech

Notice

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

Status

    Complete. Approved by the ARB on June 3, 2013.
    Ratified by the Khronos Board of Promoters on July 19, 2013.

Version

    Last Modified Date:         May 30, 2013
    Revision:                   10

Number

    ARB Extension #147

Dependencies

    This extension is written against the OpenGL 4.3 (Compatibility Profile)
    Specification, dated August 6, 2012.

    OpenGL 3.0 is required.

    This extension interacts with OpenGL 3.3 and ARB_sampler_objects.

    This extension interacts with OpenGL 4.3 and ARB_vertex_attrib_binding.

Overview

    This extension provides a new set of commands allowing applications to
    bind or unbind a set of objects in a single call, instead of requiring a
    separate call for each bind or unbind operation.  Using a single command
    allows OpenGL implementations to amortize function call, name space
    lookup, and potential locking overhead over multiple bind or unbind
    operations.  The rendering loops of graphics applications frequently
    switch between different states, binding different sets of resources,
    including texture objects, sampler objects, textures for image loads and
    stores, uniform buffers, and vertex buffers; this extension provides
    "multi-bind" entry points for all of these object types.

    Each command in this extension includes a <first> and <count> parameter,
    specifying a continguous range of binding points to update, as well as an
    array of <count> object names specifying the objects to bind.  Unlike
    single bind commands, multi-bind commands can be used only to bind or
    unbind existing objects.  Passing a previously unused object name
    (generated or not) results in an error and does not create a new object.
    For binding points with associated data (e.g., ranges of a buffer),
    separate arrays are used to pass the associated data for each binding
    point.  Passing zero values in the array of object names removes the
    object bound to the current bounding point.  Additionally, if NULL is
    passed as the array of objects, objects bound to the entire range of
    binding points are unbound, as though the caller passed an array of
    zeroes.

New Procedures and Functions

    void BindBuffersBase(enum target, uint first, sizei count, 
                         const uint *buffers);

    void BindBuffersRange(enum target, uint first, sizei count, 
                          const uint *buffers, const intptr *offsets,
                          const sizeiptr *sizes);

    void BindTextures(uint first, sizei count, const uint *textures);

    void BindSamplers(uint first, sizei count, const uint *samplers);

    void BindImageTextures(uint first, sizei count, const uint *textures);

    void BindVertexBuffers(uint first, sizei count, const uint *buffers,
                           const intptr *offsets, const sizei *strides);

New Tokens

    None.

Modifications to the OpenGL 4.3 (Compatibility Profile) Specification

    Modify Section 2.3.1, Errors, p. 15

    (modify third paragraph, p. 16, adding "unless otherwise noted"
     qualification to the general rule that commands producing errors have no
     side effects)

    Table 2.3 summarizes ...  if an OUT_OF_MEMORY error has occurred.  In
    other cases, there are no side effects unless otherwise noted; the command
    which generates the error is ignored so that it has no effect on GL state
    or framebuffer contents. ...


    Modify Section 6.1.1, Binding Buffer Objects To Indexed Targets, p. 55

    (insert immediately after the "Errors" block at the end of the section,
    p. 56)

    The commands

      void BindBuffersBase(enum target, uint first, sizei count, 
                           const uint *buffers);

      void BindBuffersRange(enum target, uint first, sizei count, 
                            const uint *buffers, const intptr *offsets,
                            const sizeiptr *sizes);

    bind <count> existing buffer objects to bindings numbered <first> through
    <first>+<count>-1 in the array of buffer binding points corresponding to
    <target>.  If <buffers> is not NULL, it specifies an array of <count>
    values, each of which must be zero or the name of an existing buffer
    object.  For BindBuffersRange, <offsets> and <sizes> specify arrays of
    <count> values indicating the range of each buffer to bind.  If <buffers>
    is NULL, all bindings from <first> through <first>+<count>-1 are reset
    to their unbound (zero) state. In this case, the offsets and sizes
    associated with the binding points are set to default values, ignoring
    <offsets> and <sizes>.

    BindBuffersBase is equivalent to:

      for (i = 0; i < count; i++) {
        if (buffers == NULL) {
          glBindBufferBase(target, first + i, 0);
        } else {
          glBindBufferBase(target, first + i, buffers[i]);
        }
      }

    except that the single general buffer binding corresponding to <target>
    is unmodified, and that buffers will not be created if they do not
    exist.

    BindBuffersRange is equivalent to:

      for (i = 0; i < count; i++) {
        if (buffers == NULL) {
          glBindBufferRange(target, first + i, 0, 0, 0);
        } else {
          glBindBufferRange(target, first + i, buffers[i], offsets[i], 
                            sizes[i]);
        }
      }

    except that the single general buffer binding corresponding to <target>
    is unmodified, and that buffers will not be created if they do not
    exist.

    The values specified in <buffers>, <offsets>, and <sizes> will be checked
    separately for each binding point.  When values for a specific binding
    point are invalid, the state for that binding point will be unchanged and
    an error will be generated.  However, state for other binding points will
    still be changed if their corresponding values are valid.

    Errors

      An INVALID_ENUM error is generated if <target> is not one of the targets
      listed above.

      An INVALID_OPERATION error is generated if <first> + <count> is greater
      than the number of target-specific indexed binding points, as described
      in section 6.7.1.

      An INVALID_OPERATION error is generated if any value in <buffers> is not
      zero or the name of an existing buffer object (per binding).

      An INVALID_VALUE error is generated by BindBuffersRange if any value in
      <offsets> is less than zero (per binding).

      An INVALID_VALUE error is generated by BindBuffersRange if any value in
      <sizes> is less than or equal to zero (per binding).

      An INVALID_VALUE error is generated by BindBuffersRange if any pair of
      values in <offsets> and <sizes> does not respectively satisfy the
      constraints described for those parameters for the specified target, as
      described in section 6.7.1 (per binding).


    Modify Section 8.1, Texture Objects (p. 155)

    (insert after errors section, p. 156)

    The command

      void BindTextures(uint first, sizei count, const uint *textures);

    binds <count> existing texture objects to texture image units numbered
    <first> through <first>+<count>-1.  If <textures> is not NULL, it
    specifies an array of <count> values, each of which must be zero or the
    name of an existing texture object.  When an entry in <textures> is the
    name of an existing texture object, that object is bound to corresponding
    texture unit for the target specified when the texture object was created.
    When an entry in <textures> is zero, each of the targets enumerated at the
    beginning of this section is reset to its default texture for the
    corresponding texture image unit.  If <textures> is NULL, each target of
    each affected texture image unit from <first> through <first>+<count>-1 is
    reset to its default texture.

    BindTextures is equivalent to

      for (i = 0; i < count; i++) {
        uint texture;
        if (textures == NULL) { 
          texture = 0;
        } else {
          texture = textures[i];
        }
        ActiveTexture(TEXTURE0 + first + i);
        if (texture != 0) {
          enum target = /* target of texture object textures[i] */;
          BindTexture(target, textures[i]);
        } else {
          for (target in all supported targets) {
            BindTexture(target, 0);
          }
        }
      }

    except that the active texture selector retains its original value upon
    completion of the command, and that textures will not be created if they
    do not exist.


    The values specified in <textures> will be checked separately for each
    texture image unit.  When a value for a specific texture image unit is
    invalid, the state for that texture image unit will be unchanged and an
    error will be generated.  However, state for other texture image units
    will still be changed if their corresponding values are valid.

    Errors

      An INVALID_OPERATION error is generated if <first> + <count> is greater
      than the number of texture image units supported by the implementation.

      An INVALID_OPERATION error is generated if any value in <textures> is
      not zero or the name of an existing texture object (per binding).


    Modify Section 8.2, Sampler Objects (p. 158)

    (insert after errors section, p. 159)

    The command

      void BindSamplers(uint first, sizei count, const uint *samplers);

    binds <count> existing sampler objects to texture image units numbered
    <first> through <first>+<count>-1.  If <samplers> is not NULL, it
    specifies an array of <count> values, each of which must be zero or the
    name of an existing sampler object.  If <samplers> is NULL, each affected
    texture image unit from <first> through <first>+<count>-1 will be reset to
    have no bound sampler object.

    BindSamplers is equivalent to

      for (i = 0; i < count; i++) {
        if (samplers == NULL) {
          glBindSampler(first + i, 0);
        } else {
          glBindSampler(first + i, samplers[i]);
        }
      }

    The values specified in <samplers> will be checked separately for each
    texture image unit.  When a value for a specific texture image unit is
    invalid, the state for that texture image unit will be unchanged and an
    error will be generated.  However, state for other texture image units
    will still be changed if their corresponding values are valid.

    Errors

      An INVALID_OPERATION error is generated if <first> + <count> is greater
      than the number of texture image units supported by the implementation.

      An INVALID_OPERATION error is generated if any value in <samplers> is
      not zero or the name of an existing sampler object (per binding).


    Modify Section 8.25, Texture Image Loads and Stores, p. 281

    (insert before the next-to-last paragraph, p. 282, "When a shader
     accesses...")

    The command

      void BindImageTextures(uint first, sizei count, const uint *textures);

    binds <count> existing texture objects to image units numbered <first>
    through <first>+<count>-1.  If <textures> is not NULL, it specifies an
    array of <count> values, each of which must be zero or the name of an
    existing texture object.  If <textures> is NULL, each affected image unit
    from <first> through <first>+<count>-1 will be reset to have no bound
    texture object.

    When binding a non-zero texture object to an image unit, the image unit
    <level>, <layered>, <layer>, and <access> parameters are set to zero,
    TRUE, zero, and READ_WRITE, respectively.  The image unit <format>
    parameter is taken from the internal format of the texture image at level
    zero of the texture object identified by <textures>.  For cube map
    textures, the internal format of the TEXTURE_CUBE_MAP_POSITIVE_X image of
    level zero is used.  For multisample, multisample array, buffer, and
    rectangle textures, the internal format of the single texture level is
    used.

    When unbinding a texture object from an image unit, the image unit
    parameters <level>, <layered>, <layer>, and <format> will be reset to
    their default values of zero, FALSE, 0, and R8, respectively.

    BindImageTextures is equivalent to

      for (i = 0; i < count; i++) {
        if (textures == NULL || textures[i] = 0) {
          glBindImageTexture(first + i, 0, 0, FALSE, 0, READ_ONLY, R8);
        } else {
          glBindImageTexture(first + i, textures[i], 0, TRUE, 0, READ_WRITE,
                             lookupInternalFormat(textures[i]));
        }
      }

    where lookupInternalFormat returns the internal format of the specified
    texture object.

    The values specified in <textures> will be checked separately for each
    image unit.  When a value for a specific image unit is invalid, the state
    for that image unit will be unchanged and an error will be generated.
    However, state for other image units will still be changed if their
    corresponding values are valid.

    Errors

      An INVALID_OPERATION error is generated if <first> + <count> is greater
      than the number of image units supported by the implementation.

      An INVALID_OPERATION error is generated if any value in <textures> is
      not zero or the name of an existing texture object (per binding).

      An INVALID_OPERATION error is generated if the internal format of the
      level zero texture image of any texture in <textures> is not found in
      table 8.33 (per binding).

      An INVALID_OPERATION error is generated if the width, height, or depth
      of the level zero texture image of any texture in <textures> is zero
      (per binding).


    Modify Section 10.3.1, Specifying Arrays For Generic Attributes, p. 340

    (insert after first errors section, p. 343)

    The command

      void BindVertexBuffers(uint first, sizei count, const uint *buffers,
                             const intptr *offsets, const sizei *strides);

    binds <count> existing buffer objects to vertex buffer binding points
    numbered <first> through <first>+<count>-1.  If <buffers> is not NULL, it
    specifies an array of <count> values, each of which must be zero or the
    name of an existing buffer object.  <offsets> and <strides> specify arrays
    of <count> values indicating the offset of the first element and stride
    between elements in each buffer, respectively.  If <buffers> is NULL, each
    affected vertex buffer binding point from <first> through
    <first>+<count>-1 will be reset to have no bound buffer object.  In this
    case, the offsets and strides associated with the binding points are set
    to default values, ignoring <offsets> and <strides>.

    BindVertexBuffers is equivalent to

      for (i = 0; i < count; i++) {
        if (buffers == NULL) {
          glBindVertexBuffer(first + i, 0, 0, 16);
        } else {
          glBindVertexBuffer(first + i, buffers[i], offsets[i], strides[i]);
        }
      }

    except that buffers will not be created if they do not exist.

    The values specified in <buffers>, <offsets>, and <strides> will be
    checked separately for each vertex buffer binding point.  When a value for
    a specific binding point is invalid, the state for that binding point will
    be unchanged and an error will be generated.  However, state for other
    binding points will still be changed if their corresponding values are
    valid.

    Errors

      An INVALID_OPERATION error is generated if <first> + <count> is greater
      than the value of MAX_VERTEX_ATTRIB_BINDINGS.

      An INVALID_OPERATION error is generated if any value in <buffers> is not
      zero or the name of an existing buffer object (per binding).

      An INVALID_VALUE error is generated if any value in <offsets> or
      <strides> is negative (per binding).


    Modify Section 21.4.1, Commands Not Usable in Display Lists, p. 618

    (add a new section below "Debug output", p. 619)

    Multi-object binds:  BindBuffersBase, BindBuffersRange, BindTextures,
    BindSamplers, BindImageTextures, BindVertexBuffers


Additions to the AGL/EGL/GLX/WGL Specifications

    None

GLX Protocol

    TBD

Dependencies on OpenGL 3.3 and ARB_sampler_objects

    If neither OpenGL 3.3 nor ARB_sampler_objects is supported, references to
    BindSamplers should be removed.

Dependencies on OpenGL 4.3 and ARB_vertex_attrib_binding

    If neither OpenGL 4.3 nor ARB_vertex_attrib_binding is supported,
    references to BindVertexBuffers should be removed.

Errors

    An INVALID_ENUM error is generated by BindBuffersBase or BindBuffersRange
    if <target> is not one of the indexed targets for buffer bindings.

    An INVALID_OPERATION error is generated by BindBuffersBase or
    BindBuffersRange if <first> + <count> is greater than the number of
    target-specific indexed binding points, as described in section 6.7.1.

    An INVALID_OPERATION error is generated by BindBuffersBase or
    BindBuffersRange if any value in <buffers> is not zero or the name of an
    existing buffer object (per binding).

    An INVALID_VALUE error is generated by BindBuffersRange if any value in
    <offsets> is less than zero (per binding).

    An INVALID_VALUE error is generated by BindBuffersRange if any value in
    <sizes> is less than or equal to zero (per binding).

    An INVALID_VALUE error is generated by BindBuffersRange if any pair of
    values in <offsets> and <sizes> do not respectively satisfy the
    constraints described for those parameters for the specified target, as
    described in section 6.7.1 (per binding).

    An INVALID_OPERATION error is generated by BindTextures if <first> +
    <count> is greater than the number of texture image units supported by the
    implementation.

    An INVALID_OPERATION error is generated by BindTextures if any value in
    <textures> is not zero or the name of an existing texture object (per
    binding).

    An INVALID_OPERATION error is generated by BindSamplers if <first> +
    <count> is greater than the number of texture image units supported by the
    implementation.

    An INVALID_OPERATION error is generated by BindSamplers if any value in
    <samplers> is not zero or the name of an existing texture object (per
    binding).

    An INVALID_OPERATION error is generated by BindImageTextures if <first> +
    <count> is greater than the number of image units supported by the
    implementation.

    An INVALID_OPERATION error is generated by BindImageTextures if any value
    in <textures> is not zero or the name of an existing texture object (per
    binding).

    An INVALID_OPERATION error is generated by BindImageTextures if the
    internal format of the level zero texture image of any texture in
    <textures> is not found in table 8.33 (per binding).

    An INVALID_OPERATION error is generated by BindImageTextures if the width,
    height, or depth of the level zero texture image of any texture in
    <textures> is zero (per binding).

    An INVALID_OPERATION error is generated by BindVertexBuffers if <first> +
    <count> is greater than the value of MAX_VERTEX_ATTRIB_BINDINGS.

    An INVALID_OPERATION error is generated by BindVertexBuffers if any value
    in <buffers> is not zero or the name of an existing texture object (per
    binding).

    An INVALID_VALUE error is generated by BindVertexBuffers if any value in
    <offsets> or <strides> is negative (per binding).

New State

    None.

New Implementation Dependent State

    None.

Issues

    (1) Regular binding commands such as BindBuffer or BindTexture can be used
        either to bind an existing object or to create and bind a new object.
        Should the multi-bind commands behave similarly?

      RESOLVED:  No.  Multi-Bind commands will only support binding existing
      objects.  They will generate an error if any of the provided objects
      doesn't already exist.

      This extension is intended to provide efficient APIs allowing
      applications to bind multiple objects for rendering in a single command.
      Implementations of these commands are intended to bind the objects to
      consecutive binding points in a loop amortizing function call, name
      space lookup, locking, and other overhead over <N> objects.  Not
      supporting bind-to-create reduces the number of cases that this loop
      needs to handle.

      Even if bind-to-create were supported, it probably wouldn't be very
      useful.  When bind-to-create is used in current single-bind APIs, the
      binding serves two purposes -- to create the object and to bind it for
      use by subsequent "update" APIs defining the state of the new object.
      In a multi-Bind API, it wouldn't be possible to bind more than one of
      the <N> objects for update.

      Additionally, if BindTexture is used to create a texture object, the
      texture type is established based on the <target> parameter (e.g.,
      TEXTURE_2D).  The multi-Bind API for textures doesn't include <target>
      parameters, so we wouldn't know what type of texture to create.

    (2) Should we provide a command binding multiple texture objects of
        different targets (e.g., TEXTURE_2D and TEXTURE_3D) in a single call?
        For example, should you be able to bind three 2D textures to the
        TEXTURE_2D target of image units 1, 2, and 3, as well as binding two
        3D textures to the TEXTURE_3D target of texture image units 0 and 4?

      RESOLVED:  Yes.  The BindTextures() command does not take <target>
      enums.  Instead, the target used for each texture image unit comes from
      the target used when the texture object was created.

    (3) Should we support unbinding objects in a multi-bind command?  If so,
        how does this work for texture objects, where each texture image unit
        has multiple binding points (targets)?

      RESOLVED:  Yes, applications can unbind objects by passing zero in the
      array of object names.  For textures, passing zero will unbind textures
      from all texture targets.

    (4) Should we provide a simple way to unbind objects from a collection of
        contiguous binding points?

      RESOLVED:  Yes, passing a NULL pointer instead of an array of object
      names does an unbind for all binding points.  Basically, it's treated
      like an array of zeroes.

    (5) Should we support multiple bindings of buffer objects using both the
        "BindBufferBase" and the "BindBufferRange" styles?  If so, what name
        should we use for these APIs?

      RESOLVED:  Yes.  BindBuffersBase() is equivalent to a loop repeatedly
      calling BindBufferBase(); BindBuffersRange() is equivalent to a loop
      repeatedly calling BindBufferRange().

      The name choice for the "plural" forms of BindBufferBase and
      BindBufferRange was tricky.  "BindBufferRanges" would have been a fine
      choice for BindBufferRange, but using "BindBufferBases" would have been
      strange since "BindBufferBase" means "bind a buffer from the base of its
      storage (offset zero)".  We considered "BindBuffers" as the plural for
      "BindBufferBase", but decided to use "BindBuffers{Base,Range}".

    (6) If we support multiple bindings using the BindBufferRange style, how
        should the application specify the ranges?

      RESOLVED:  Applications will pass separate arrays of offsets and sizes.

      Alternate options included:

        * a single array where entry 2<N> specifies the offset for binding <N>
          and entry 2<N>+1 specifies the size for binding <N>;

        * defining a new structure type including an offset and a size, and
          accepting an array of <N> structures

    (7) Should we create a "multi-bind" command for specifying vertex buffer
        bindings (those specified via BindVertexBuffer)?

      RESOLVED:  Yes.

    (8) If we add a "multi-bind" command for specifying vertex buffer
        bindings, should we also create a similar command for specifying
        multiple vertex formats (VertexAttrib*Format) in a single call?

      RESOLVED:  No.  The design of ARB_vertex_attrib_binding separated
      vertex buffer bindings from vertex formats, expecting that many
      applications will change bindings frequently but change formats
      relatively infrequently.  While we could create a command specifying
      multiple formats at once, but it would require us to turn several format
      parameters (<size>, <type>, <normalized>, <relativeoffset>) into arrays.

      Additionally, mutable vertex array objects can already be used to make a
      wholesale change of formats and bindings.  An application using a small
      number of formats with a large number of bindings could create a
      separate VAO for each format, and then change bindings with the
      "multi-bind" command.

    (9) Should we provide a command to specify multiple image unit bindings in
        a single command?

      RESOLVED:  Yes.  We decided to support this for completeness, though the
      required number of image units is relatively small (8).

    (10) Should binding an array of buffer objects via BindBuffersBase or
         BindBuffersRange update the generic (non-indexed) binding points for
         <target>?

      RESOLVED:  No.

      In unextended OpenGL 4.3, targets like UNIFORM_BUFFER include both an
      array of indexed bindings used for shader execution as well as a generic
      "non-indexed" binding point that can be used for commands such as
      BufferSubData.  Calling BindBufferBase or BindBufferRange updates two
      binding points -- binding <index> in the array of indexed bindings as
      well as the generic binding point.  Updating both binding points allows
      applications to bind a buffer for manipulation and update in a single
      command.

      For BindBuffersBase and BindBuffersRange, the caller specifies <count>
      separate buffers.  We have specified these commands not to update the
      generic binding point.  Even if we were to update the generic binding
      point, we'd have to pick one arbitrarily.

    (11) Typically, OpenGL specifies that if an error is generated by a
         command, that command has no effect.  This is somewhat unfortunate
         for multi-bind commands, because it would require a first pass to
         scan the entire list of bound objects for errors and then a second
         pass to actually perform the bindings.  Should we have different
         error semantics?

      RESOLVED:  Yes.  In this specification, when the parameters for one of
      the <count> binding points are invalid, that binding point is not
      updated and an error will be generated.  However, other binding points
      in the same command will be updated if their parameters are valid and no
      other error occurs.

    (12) What error should be generated if the <first> and <count> parameters
         specified in multi-bind commands specify a range beyond
         implementation-dependent limits?

      RESOLVED:  INVALID_OPERATION is typically generated when the
      combination of two values is illegal.  INVALID_VALUE would also be
      defensible.

    (13) How are the <offsets> and <sizes> parameters of BindBuffersRange used
         if <buffers> is NULL?

      RESOLVED:  We specify that these parameters are ignored when buffers
      is NULL, so that applications can unbind a range of buffers with:

        BindBuffersRange(target, 0, 8, NULL, NULL, NULL);

    (14) Should we provide a "multi-bind" API to attach multiple textures to
         the color attachments of a framebuffer object?  Should we add an API
         populating all attachments at once?

      RESOLVED:  No.  We could consider an API like:

        void FramebufferColorTextures(enum target, uint first, sizei count,
                                      const uint *textures, 
                                      const uint *levels);

      One might omit the <levels> parameter, since level 0 is used most
      frequently, and non-zero levels could still be handled by creating
      spearate views via ARB_texture_view.  If we wanted to be able to specify
      the full set of attachments at once, we could have:

        void FramebufferTextures(enum target, sizei count,
                                 const uint *colorAttachments,
                                 const uint depthAttachment,
                                 const uint stencilAttachment);

      This API effectively omits the <first> argument and always starts at
      zero.  The "all attachments" API could be handled in OpenGL today by
      using separate framebuffer objects for each attachment combination.
      However, for applications that work with various combinations of
      attachments but don't already have a notion of "attachment sets" to map
      to framebuffer objects, caching different attachment combinations is
      somewhat unwieldy.

    (15) Should we provide a multi-bind API that binds pairs of textures and
    samplers to a set of consecutive texture image units?

      RESOLVED:  No.  We could provide a command such as:

        void BindTexturesSamplers(uint first, sizei count,
                                  const uint *textures, 
                                  const uint *samplers);

      that would be roughly equivalent to:

        BindTextures(first, count, textures);
        BindSamplers(first, count, samplers);

      If we did this, we'd have to decide how it would interact with the error
      semantics in issue (11).  If we have an error generated because of an
      invalid texture for a given unit, would the sampler state for that unit
      still be updated if the sampler provided were valid?  Since we chose not
      to support this feature, we don't need to address this question.

    (16) When binding a non-zero texture to a texture image unit, should
         BindTextures implicitly unbind the textures bound to all other
         targets of the unit?

      RESOLVED:  No.

      This approach was considered to behave similarly to the proposed
      behavior for binding zero in a multi-bind API, where it unbinds any
      bound texture for all targets.  Applications using BindTextures
      exclusively would never have more than one texture bound to the targets
      of a texture image unit.  A driver implementation might optimize for
      this behavior by having a single "primary" binding point for each
      texture unit (used by this API) and then "backup" binding points for the
      other targets (used by BindTexture).  This API would update the
      "primary" binding point but would only need to touch the "backup"
      binding points if something were bound there via BindTexture.  However,
      BindTexture would still be available and is commonly used today, so
      there would probably be little benefit.

    (17) For the BindTextures API, should the <first> parameter be an unsigned
         integer (0) or an enum (GL_TEXTURE0)?

      RESOLVED:  Use an integer unit number.

    (18) The BindImageTexture API not only binds a texture to an image unit,
         but also sets several additional pieces of state associated with an
         image unit (level, layered or not, selected layer, and image unit
         format).  How should this state be set?  Should we provide separate
         arrays for each extra parameter?

      RESOLVED:  Use "default" values for each image unit.  When unbinding
      textures, reset the state to API defaults (level zero, non-layered,
      layer zero, and R8 format).  When binding textures, bind all layers of
      level zero and take the format from the internal format of the texture
      level being bound.  Setting <layered> to TRUE in this case is not the
      default state, but it seems like the best default choice for cube map or
      array textures.  For textures without layers, the <layered> parameter
      has no effect, so this doesn't cause any problems with other targets
      like TEXTURE_2D.

      If an application wants to bind levels other than zero, select
      individual layers of a level for array textures, or use a format
      different from that of the texture, it will be necessary to do
      individual bindings via BindImageTexture.

    (19) If a texture bound to an image unit via BindImageTextures doesn't
         have a defined texture image (i.e., width = height = 0 for 2D
         textures), what internal format is associated with the binding?

      UNRESOLVED:  We will generate INVALID_OPERATION if there is no defined
      texture image.

      Note that even if a texture level has no texels defined, there is still
      an <internalformat> associated with the level, which can be queried with
      GetTexLevelParameter.  That value could be used, but it would still have
      to be checked to see if it's valid for image loads and stores.
      BindImageTexture doesn't accept all possible <format> enums.
      Additionally, the default internal format is profile-dependent:  core
      uses "RGBA", compatibility uses "1" (from OpenGL 1.0, meaning
      LUMINANCE).  Neither is accepted by BindImageTexture, though RGBA might
      be mapped internally by a driver to an internal format like RGBA8 that
      is accepted.

      Given the potential confusion over the internal format for zero-sized
      images and default internal formats, it's best to just not accept
      textures without defined images.

    (20) The BindBuffersRange and BindVertexBuffers accept arrays of "intptr"
         and "sizeiptr" values, which will have different sizes on 32- and
         64-bit architectures.  Is there any problem here?

      RESOLVED:  The API is fine.  Application developers will need to be
      careful to use the correct data type for the arrays it passes to these
      commands.  If the array passed to <offsets> is an array of "int" instead
      of "intptr", that code will typically work fine when compiled on 32-bit
      architectures if "int" types are stored as 32-bit values.  But if the
      same code is compiled for a 64-bit architecture, the array will be too
      small.  We expect that compilers will generate warnings and/or errors
      if the caller passes a pointer to the wrong type.

    (21) In the compatibility profile, can multi-bind commands be included in
         display lists?

      RESOLVED:  No.

    (22) What error should be generated when one of the names passed to a
         multi-bind command is not the name of an existing object?

      UNRESOLVED:  INVALID_OPERATION.  For the core profile, as well as for
      object types created since OpenGL 3.1, we have spec errors like the
      following for BindTexture:

        An INVALID_OPERATION error is generated if <texture> is not zero or a
        name returned from a previous call to GenTextures, or if such a name
        has since been deleted.

      In issue (1), we decided that the multi-bind commands could not be used
      to create objects, whether or not the object names had previously been
      returned by commands like GenTextures.  The errors we require for the
      multi-bind commands are different from the BindTexture language quoted
      immmediately above only in the sense that the multi-bind will
      additionally throw an error if a texture name has been generated by
      GenTextures but the underlying texture object hasn't yet been created.
      However, the errors are similar enough that they should both throw the
      same error code (INVALID_OPERATION).


Revision History

    Revision 11, August 16, 2013 (Jon Leech)
      - Typo fix for BindBuffers* "offsets and strides" -> "offsets and
        sizes" (Bug 10685).
    Revision 10, July 21, 2013 (Jon Leech)
      - Specify that multibind commands are equivalent to repeated calls to
        the corresponding single bind commands except that objects are not
        created if they do not exist, matching issue 1. The other single
        bind commands do not create objects so this clarification is not
        needed for them (Bug 10486).

    Revision 9, May 30, 2013 (Jon Leech)
      - Fix typo for <offsets> "less than to zero" -> "less than zero". Use
        "<first> *through* <first> + <count> - 1" consistently.

    Revision 8, May 28, 2013
      - Change the error thrown when an object name passed to a multi-bind
        command doesn't yet exist from INVALID_VALUE to INVALID_OPERATION 
        (bug 10264).
      - Disallow the use of multi-bind commands in display lists (bug 10322).
      - Change the <count> parameter in multi-bind commands to use the type
        "sizei" to be consistent with other GL commands accepting a <count>
         parameter (bug 10323).
      - Clarify that passing NULL in arguments like <buffers> only affect
        bindings <first> through <first>+<count>-1 (bug 10289).
      - In the errors section for multi-bind commands, clarify which errors
        apply to only a single binding and which apply to the entire call (bug
        10289). 
      - Clarify in the spec language that BindImageTextures sets <access> to
        READ_WRITE for all bindings, which was already in the pseudocode (bug
        10289).
      - Use the term "general buffer binding" in spec language stating that
        BindBuffersBase and BindBuffersRange only affect numbered binding
        points (bug 10289).
      - Add issues (21) and (22).

    Revision 7, May 18, 2013
      - Fix typo in the description of BindSamplers.

    Revision 6, May 17, 2013
      - Modify the pseudocode for BindTextures to add in TEXTURE0 to the
        value passed to ActiveTexture, since it takes an enum and not an
        integer.

    Revision 5, May 10, 2013
      - Define lookupInternalFormat in pseudocode example.

    Revision 4, May 2, 2013
      - Renamed entry points for buffer bindings from BindBuffers() and
        BindBufferRanges() to BindBuffersBase() and BindBuffersRange(),
        respectively.
      - Add an INVALID_OPERATION error if a non-zero texture passed to
        BindImageTextures() does not have a defined image array.
      - Add an "unless otherwise noted" qualification to the general spec rule
        that commands producing errors do not modify the GL state.  Multi-bind
        commands have special error behavior discussed in issue (11).
      - Mark issues resolved based on previous spec reviews.
      - Added issue (20).

    Revision 3, April 19, 2013
      - Add a BindImageTextures API to bind a collection of textures to image
        units (for shader image loads/stores).
      - Fix the spec to consistently use the parameter name <first> to
        identify the first binding point to update.
      - Add new issues.

    Revision 2, January 20, 2013
      - Fix various specification errors.
      - Add an issue about whether we should provide a multi-bind API for
        framebuffer object attachments.

    Revision 1, January 18, 2013
      - Initial revision.
