Name

    ARB_transform_feedback3

Name Strings

    GL_ARB_transform_feedback3

Contact

    Pat Brown (pbrown 'at' nvidia.com)
    
Contributors

    Barthold Lichtenbelt, NVIDIA
    Bill Licea-Kane, AMD
    Bruce Merry, ARM
    Graham Sellers, AMD
    Greg Roth, NVIDIA
    Jeff Bolz, NVIDIA
    Nick Haemel, AMD
    Pierre Boudier, AMD
    Piers Daniell, NVIDIA

Notice

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

Status

    Complete. Approved by the ARB at the 2010/01/22 F2F meeting.
    Approved by the Khronos Board of Promoters on March 10, 2010.

Version

    Last Modified Date:         03/23/2010
    Revision:                   12

Number

    ARB Extension #94

Dependencies

    EXT_transform_feedback, NV_transform_feedback, or OpenGL 3.0 is required.

    OpenGL 2.0 is required.

    This extension interacts with EXT_transform_feedback,
    NV_transform_feedback, and NV_transform_feedback2.

    This extension interacts with ARB_gpu_shader5 and NV_gpu_program5.

    This extension is written against the OpenGL 3.2 specification (Core 
    Profile).

    This extension builds up and is written against various language in the
    EXT_transform_feedback and NV_transform_feedback specifications.

Overview

    This extension further extends the transform feedback capabilities
    provided by the EXT_transform_feedback, NV_transform_feedback, and
    NV_transform_feedback2 extensions.  Those extensions provided a new
    transform feedback mode, where selected vertex attributes can be recorded
    to a buffer object for each primitive processed by the GL.

    This extension provides increased flexibility in how vertex attributes can
    be written to buffer objects.  Previous extensions allowed applications to
    record a set of attributes interleaved into a single buffer object
    (interleaved mode) or to record into multiple objects, but with only a
    single attribute per buffer (separate mode).  This extension extends
    interleaved mode to write into multiple buffers, with multiple attributes
    per buffer.  This capability is supported for all three styles of
    transform feedback:

      - "EXT"-style GLSL transform feedback (EXT_transform_feedback), where a
         list of varyings is provided prior to linking a program object and is
         used whenever that program object is used.

      - "NV"-style GLSL transform feedback (NV_transform_feedback), where
        "locations" of active varyings are queried after linking and are then
        passed to a function that sets the active transform feedback varyings
        for the program object.  Unlike the "EXT"-style mode, the set of
        varyings to capture can be changed without relinking.

      - Transform feedback for fixed-function or assembly vertex/geometry
        shaders (NV_transform_feedback), where applications specify a set of
        canonical attribute enums/numbers to capture.

    Additionally, this extension adds new support for multiple separate
    vertex streams.  New geometry shader functionality provided by the
    ARB_gpu_shader5 and NV_gpu_program5 extensions allows geometry shaders
    to direct each vertex arbitrarily at a specified vertex stream.  For
    example, a geometry program might write each "regular" vertex it emits
    to one vertex stream while writing some per-primitive data it computes
    to a second vertex stream.  This extension allows applications to
    choose a vertex stream for each buffer object it writes to, and allows
    the vertices written to each vertex stream to be recorded in separate
    buffer objects.  Only one stream may be selected for rasterization,
    and in the initial implementation, the geometry shader output topology
    must be POINTS if multiple streams are used.  When geometry shaders
    are not used, or when an old geometry shader not writing multiple
    streams is used, all vertices produced by the GL are directed at the
    stream numbered zero.  The set of transform feedback-related query
    targets is extended to accommodate multiple vertex streams, so it is
    possible to count the number of processed and recorded primitives for
    each stream separately.

IP Status

    No known IP claims.

New Procedures and Functions

    void DrawTransformFeedbackStream(enum mode, uint id, uint stream);
    void BeginQueryIndexed(enum target, uint index, uint id);
    void EndQueryIndexed(enum target, uint index);
    void GetQueryIndexediv(enum target, uint index, enum pname, int *params);

New Tokens

    Accepted by the <pname> parameter of GetBooleanv, GetDoublev, GetIntegerv,
    and GetFloatv:

      MAX_TRANSFORM_FEEDBACK_BUFFERS                    0x8E70
      MAX_VERTEX_STREAMS                                0x8E71

Additions to Chapter 2 of the OpenGL 3.2 Specification (OpenGL Operation)

    (Modify the error behavior of transform feedback buffer binding APIs to
     treat the new constant MAX_TRANSFORM_FEEDBACK_BUFFERS as the number of 
     binding points.)

    Buffer objects are made to be targets of transform feedback by calling one
    of the commands

      void BindBufferRange(enum target, uint index, uint buffer,
                              intptr offset, sizeiptr size);
      void BindBufferBase(enum target, uint index, uint buffer);

    ...  The error INVALID_VALUE is generated if <index> is greater than or
    equal to the value of MAX_TRANSFORM_FEEDBACK_BUFFERS.

    ...

    Transform feedback can operate using one of two buffer modes.  In
    interleaved mode, the values of one or more varying variables written by a
    vertex or geometry shader are written, interleaved, into the buffer
    objects bound to one or more transform feedback binding points.  The list
    of varyings provided for capture in interleaved mode may include special
    separator values, which can be used to direct subsequent varyings to the
    next binding point.  Each non-separator varying is written to the binding
    point numbered <n>, where <n> is the number of separator values preceding
    it in the list.  If more than one varying variable is written to a buffer
    object, they will be recorded in the order specified by
    TransformFeedbackVaryings (section 2.11.6).  In separate mode, the first
    varying variable specified by TransformFeedbackVaryings is written to
    the first transform feedback binding point; subsequent varying variables
    are written to the subsequent transform feedback binding points.

    When using a geometry shader or program that writes vertices to multiple
    vertex streams, each vertex emitted may trigger a new primitive in the
    vertex stream to which it was emitted.  If transform feedback is active,
    the varyings of the primitive are written to a transform feedback binding
    point if and only if the varyings directed at that binding point belong to
    the vertex stream in question.  All varyings assigned to a given binding
    point are required to come from a single vertex stream.
    
    ...
    

    (Modify Section 2.14, Asynchronous Queries)

    After the description of BeginQuery, p.91:

    Query targets also support multiple indexed queries. A query object may be
    created and made active on an indexed query target by calling:

        void BeginQueryIndexed(enum target, uint index, uint id);

    <target> indicates the type of query to be performed as in BeginQuery.
    <index> is the index of the query and must be between 0 and a <target>-
    specific maximum. If <index> is outside of this range, BeginQueryIndexed will
    generate the INVALID_VALUE error. The number of indexed queries supported by
    specific targets is one, unless indicated otherwise in following sections.
    Calling BeginQuery is equivalent to calling BeginQueryIndexed with <index>
    set to zero.

    After the description of EndQuery, p.91:

    The command

        void EndQueryIndexed(enum target, uint index);

    may be used to mark the end of the query currently active at index <index>
    of <target>, and must be between zero and the <target>-specific maximum.
    If <index> is outside of this range, EndQuery will generated the INVALID_VALUE
    error. Calling EndQuery is equivalent to calling EndQueryIndexed with
    <index> set to zero.

    (Modify Section 2.17, Primitive Queries.  The only substantial change is
    to modify language to reflect that we have primitive counters for each
    vertex stream.)

    Primitive queries use query objects to track the number of primitives in
    each vertex stream that are generated by the GL and the number of
    primitives in each vertex stream that are written to buffer objects in
    transform feedback mode.

    When BeginQueryIndexed is called with a <target> of PRIMITIVES_GENERATED,
    the primitives generated count maintained by the GL for the vertex stream
    <index> is set to zero. There is a separate query counter for each stream.
    The number of vertex streams is given by the value of the implementation-
    dependent constant MAX_VERTEX_STREAMS. If <index> is not an integer in the
    range zero to the value of MAX_VERTEX_STREAMS minus one, the error
    INVALID_VALUE is generated. When a generated primitive query for a vertex
    stream is active, the primitives-generated count is incremented every time
    a primitive emitted to that stream reaches the Discarding Rasterization
    stage (see Section 3.x) right before rasterization. This counter is
    incremented whether or not transform feedback is active. This counter counts
    the number of primitives emitted by a geometry shader, if active, possibly
    further tessellated into separate primitives during the transform feedback
    stage, if active.

    When BeginQueryIndexed is called with a <target> of
    TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, the transform feedback primitives
    written count maintained by the GL for vertex stream <index> is set to zero.
    There is a separate query and counter for each vertex stream. If <index> is
    not an integer in the range zero to the value of MAX_VERTEX_STREAMS minus
    one, the error INVALID_VALUE is generated. When a transform feedback
    primitives written query for a vertex stream is active, the counter for that
    vertex stream is incremented every time the vertices of a primitive written
    to that stream are recorded into one or more buffer objects. If transform
    feedback is not active or if a primitive to be recorded does not fit in a
    buffer object, the counter is not incremented.

    These two types of queries can be used together to determine if all
    primitives in a given vertex stream have been written to the bound
    feedback buffers; if both queries are run simultaneously and the query
    results are equal, all primitives have been written to the buffer(s).  If
    the number of primitives written is less than the number of primitives
    generated, one or more buffers overflowed.


    (Modify Section 2.11.6 "Varying Variables", p. 71.)

    Each program object can specify a set of one or more vertex or geometry
    shader output variables to be recorded in transform feedback mode (see
    section 2.16). When a geometry shader is active (see section 2.12),
    transform feedback records the values of the selected geometry shader
    output variables from the emitted vertices. Otherwise, the values of the
    selected vertex shader output variables are recorded. The values to record
    are specified with the command

      void TransformFeedbackVaryings(uint program, sizei count,
                                     const char **varyings, 
                                     enum bufferMode)

    <program> specifies the program object. <count> specifies the number of
    varying variables used for transform feedback. <varyings> is an array of
    <count> zero-terminated strings specifying the names of the varying
    variables to use for transform feedback. Varying variables are written out
    in the order they appear in the array varyings. <bufferMode> is either
    INTERLEAVED_ATTRIBS or SEPARATE_ATTRIBS, and identifies the mode used to
    capture the varying variables when transform feedback is active. The error
    INVALID_VALUE is generated if program is not the name of a program object,
    or if <bufferMode> is SEPARATE_ATTRIBS and <count> is greater than the
    value of the implementation-dependent limit
    MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS.

    If a string in <varyings> is "gl_NextBuffer", it does not identify a
    varying variable, but instead serves as a buffer separator value to 
    direct subsequent varyings at the next transform feedback binding point. 
    If a string in <varyings> is "gl_SkipComponents1", "gl_SkipComponents2",
    "gl_SkipComponents3", or "gl_SkipComponents4", it also does not identify a
    specific varying variable.  Instead, such values are treated as requesting
    that the GL skip the next one to four components of varying data.
    Skipping components this way is equivalent to specifying a one- to four-
    component varying with undefined values, except that the corresponding
    memory in the buffer object is not modified.  Such array entries are
    counted as being written to the buffer object for the purposes of
    determining whether the requested attributes exceed per-buffer component
    count limits.  Each component skipped is considered to occupy a single
    float.

    The error INVALID_OPERATION is generated if any pointer in <varyings>
    identifies the special names "gl_NextBuffer", "gl_SkipComponents1",
    "gl_SkipComponents2", "gl_SkipComponents3", or "gl_SkipComponents4" and
    <bufferMode> is not INTERLEAVED_ATTRIBS, or if the number of
    "gl_NextBuffer" pointers in <varyings> is greater than or equal to the
    limit MAX_TRANSFORM_FEEDBACK_BUFFERS.

    The state set by TransformFeedbackVaryings has no effect on the execution
    of the program until <program> is subsequently linked. When LinkProgram is
    called, the program is linked so that the values of the specified varying
    variables for the vertices of each primitive generated by the GL are
    written to a single buffer object (if the buffer mode is
    INTERLEAVED_ATTRIBS) or multiple buffer objects (if the buffer mode is
    SEPARATE_ATTRIBS). A program will fail to link if:

      * the <count> specified by TransformFeedbackVaryings is non-zero, but
        the program object has no vertex or geometry shader;

      * any variable name specified in the <varyings> array is not one of
        "gl_NextBuffer", "gl_SkipComponents1", "gl_SkipComponents2",
        "gl_SkipComponents3", or "gl_SkipComponents4", and is not declared as
        an output in the geometry shader (if present) or the vertex shader (if
        no geometry shader is present);

      * any two entries in the <varyings> array specify the same varying
        variable;

      * the total number of components to capture in any varying variable in
        <varyings> is greater than the constant
        MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS and the buffer mode is
        SEPARATE_ATTRIBS;

      * the total number of components to capture is greater than the constant
        MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS and the buffer
        mode is INTERLEAVED_ATTRIBS; or

      * the set of varyings to capture to any single binding point includes
        varyings from more than one vertex stream.

    (Add a new paragraph describing the interaction of separators and
    GetTransformFeedbackVarying after the GetTransformFeedBackVarying
    description.)

    Special varying names (e.g., "gl_NextBuffer", "gl_SkipComponents1") passed
    to TransformFeedbackVaryings in the <varyings> array are counted as
    varyings to be recorded for the purposes of determining the value of
    TRANSFORM_FEEDBACK_VARYINGS and for determining the variable selected
    by <index> in GetTransformFeedbackVarying.  If <index> identifies
    "gl_NextBuffer", the values zero and NONE will be written to <size> and 
    <type>, respectively.  If <index> is of the form "gl_SkipComponents<n>", 
    the value NONE, will be written to <type> and the number of components <n>
    will be written to <size>.

    (Modify Section 2.Y.3, Transform Feedback Draw Operations, added by the
     NV_transform_feedback2 extension, to add a new DrawTransformFeedback API
     to select the vertex count from an arbitrary vertex stream.)

    ...  The number of vertices captured from each vertex stream during
    transform feedback are stored in the corresponding transform feedback
    object and may be used in conjunction with the commands

        void DrawTransformFeedback(enum mode, uint id);
        void DrawTransformFeedbackStream(enum mode, uint id, uint stream);

    to replay the captured vertices.  DrawTransformFeedbackStream is
    equivalent to calling DrawArrays with <mode> set to <mode>, <first> set to
    zero, and <count> set to the number of vertices captured from the vertex
    stream numbered <stream> the last time transform feedback was active on 
    the transform feedback object named by <id>.  The error INVALID_VALUE
    is generated if <stream> is greater than or equal to the value of
    MAX_VERTEX_STREAMS.  DrawTransformFeedback is equivalent to calling 
    DrawTransformFeedbackStream with a <stream> of zero.  The error
    INVALID_VALUE is generated if <id> is not the name of a transform feedback
    object.  The error INVALID_OPERATION is generated if
    EndTransformFeedback has never been called while the object named by
    <id> was bound.  No error is generated if the transform feedback object
    named by <id> is active; the vertex count used for the rendering operation
    is set by the previous EndTransformFeedback command.  Note that the
    vertex count is from the number of vertices recorded to the selected
    vertex stream during the transform feedback operation.  If no varyings
    belonging to the selected vertex stream are recorded, the corresponding
    vertex count will be zero even if complete primitives were emitted to the
    selected stream.
    

Additions to Chapter 3 of the OpenGL 3.2 Specification (Rasterization)

    (Modify Section 3.1, Discarding Primitives Before Rasterization.
    State that only vertices sent to stream zero are processed further.)

    (insert at the beginning of the section, prior to language explaining
    RASTERIZER_DISCARD) 

    Primitives sent to the vertex stream zero are processed further;
    primitives emitted to any other stream are discarded.  When geometry
    shaders are disabled, all vertices are considered to be emitted to stream
    zero.

Additions to Chapter 4 of the OpenGL 3.2 Specification (Per-Fragment
Operations and the Frame Buffer)

    None.


Additions to Chapter 5 of the OpenGL 3.2 (Compatibility Profile)
Specification (Special Functions)

    Modify Section 5.2, Selection, p. 351

    (modify the fourth paragraph, p. 234) In selection mode, if a point, line,
    or polygon that would otherwise be sent to the rasterizer intersects with
    the clip volume (section 2.12) then this primitive causes a selection hit.
    Coordinates produced by a RasterPos command that intersect the clip volume
    also cause a selection hit, as do the coordinates from a WindowPos
    command.  In case of polygons, no hit...


Additions to Chapter 6 of the OpenGL 3.2 Specification (State and
State Requests)

    (Modify section 6.1.6, Asynchronous Queries)

    Replace the description of GetQueryiv, p.256:

    Information about an indexed query target may be queried with the commands

        void GetQueryIndexediv(enum target, uint index, enum pname, int *params);
        void GetQueryiv(enum taret, enum pname, int *params);

    where <target> identifies the query target and must be SAMPLES_PASSED for
    occlusion queries and PRIMITIVES_GENERATED or
    TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN for primitive queries. <index> is the
    index of the query target must be between zero and a <target>-specific
    maximum. If <index> is outside of this range, GetQueryIndexediv will generate
    the INVALID_VALUE error. Calling GetQueryiv is equivalent to calling
    GetQueryIndexediv with <index> set to zero.

    If <pname> is CURRENT_QUERY, the name of the currently active query for
    index <index> of <target>, or zero if no query is active for that index
    of <target>, will be placed in <params>.

    If <pname> is QUERY_COUNTER_BITS, <index> is ignored and the implementation-
    dependent number of bits used to hold the query result for target will be
    placed in params. The number of query counter bits may be zero, in which
    case the counter contains no useful information.

    (Retain remainder of original language from description of GetQueryiv.)

    (Minor change to the Section 6.1.8 language to change error behavior
     of transform feedback query APIs to treat the new constant
     MAX_TRANSFORM_FEEDBACK_BUFFERS as the number of binding points.)

    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 <param> set to TRANSFORM_FEEDBACK_BUFFER_BINDING.
    <index> must be in the range zero to the value of
    MAX_TRANSFORM_FEEDBACK_BUFFERS - 1. The name of the buffer object bound 
    to <index> is returned in <values>. If no buffer object is bound for 
    <index>, zero is returned in <values>. The error INVALID_VALUE is
    generated if <index> 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 param
    set to TRANSFORM_FEEDBACK_BUFFER_START or TRANSFORM_FEEDBACK_BUFFER_SIZE
    respectively. <index> must be in the range 0 to the value of
    MAX_TRANSFORM_FEEDBACK_BUFFERS - 1. If the parameter (starting offset or
    size) was not specified when the buffer object was bound, zero is 
    returned. If no buffer object is bound to index, -1 is returned. The
    error INVALID_VALUE is generated if <index> is greater than or equal to
    the limit MAX_TRANSFORM_FEEDBACK_BUFFERS.

Additions to Appendix A of the OpenGL 3.2 Specification (Invariance)

    None.

Additions to the AGL/GLX/WGL Specifications

    None.

GLX Protocol

    TBD

Dependencies on NV_gpu_program5 and ARB_gpu_shader5

    If support for multiple vertex streams is not provided (by
    NV_gpu_program5, ARB_gpu_shader5, or a similar extension), the spec
    language does not need to change.  However, the value of the limit
    MAX_VERTEX_STREAMS will be 1.  In this case, the new query object
    targets, language referring to multiple vertex streams, and the
    TransformFeedbackStreamAttribsNV function (described immediately below in
    the "NV_transform_feedback" dependencies section) would be unnecessary but
    not otherwise harmful.

    We expect that some extension providing multiple vertex streams will be
    supported on all implementations of this extension.
    

Dependencies on NV_transform_feedback and NV_transform_feedback2

    If NV_transform_feedback or NV_transform_feedback2 is supported the
    following additional edits are required:
    
    New Procedures and Functions

        void TransformFeedbackStreamAttribsNV(sizei count,
                                              const int * attribs, 
                                              sizei nbuffers, 
                                              const int *bufstreams,
                                              enum bufferMode);

    New Tokens
    
        Accepted in the <locations> array of TransformFeedbackVaryingsNV
        when <bufferMode> is INTERLEAVED_ATTRIBS:

          NEXT_BUFFER_NV                                    -2
          SKIP_COMPONENTS4_NV                               -3
          SKIP_COMPONENTS3_NV                               -4
          SKIP_COMPONENTS2_NV                               -5
          SKIP_COMPONENTS1_NV                               -6

    (Modify NV_transform_feedback section that adds to Section 2.Y, Transform
    Feedback.)

    (Modify the error behavior of transform feedback buffer binding APIs to
     treat the new constant MAX_TRANSFORM_FEEDBACK_BUFFERS as the number of 
     binding points.)

    Buffer objects are made to be targets of transform feedback by calling one
    of

      void BindBufferRange(enum target, uint index, uint buffer,
                           intptr offset, sizeiptr size)
      void BindBufferOffsetNV(enum target, uint index, uint buffer,
                              intptr offset)
      void BindBufferBase(enum target, uint index, uint buffer)

    ...  The error INVALID_VALUE is generated if <index> is greater than or
    equal to the value of MAX_TRANSFORM_FEEDBACK_BUFFERS.

    ...

    (Modify the section that describes TransformFeedbackAttribsNV for
    fixed-function vertex processing.)
                              
    When no vertex or geometry shader is active, transform feedback may be
    used to record vertex attribute values written by fixed-function vertex
    processing or by an assembly vertex or geometry program.  Both buffer
    modes described above are supported.  The set of attributes recorded, and
    their order, is specified by TransformFeedbackAttribsNV (section 2.Y).
    
    (modify language from NV_transform_feedback describing
    TransformFeedbackAttribsNV, used to capture outputs from fixed-function
    and assembly programs)

    The set of vertex attributes to capture when no vertex or geometry shader
    is active is specified by the command

      void TransformFeedbackAttribsNV(sizei count, const int *attribs,
                                      enum bufferMode)

    <bufferMode> is one of INTERLEAVED_ATTRIBS or SEPARATE_ATTRIBS,
    and identifies the mode used to capture the attributes when transform
    feedback is active.  <attribs> is an array of 3*<count> values specifying
    the set of vertex attribute vectors to record.  For the <i>th attribute,
    array element 3*<i>+0 specifies the type of attribute to capture, as
    described in table X.1, or one of the special values described below.  The
    error INVALID_ENUM is generated if this value is not found in table X.1.
    Array element 3*<i>+1 specifies the number of components to record from
    the specified attribute.  The error INVALID_VALUE is generated if this
    value is not supported for the specified attribute type, as indicated in
    Table X.1.  Array element 3*<i>+2 identifies the attribute number used for
    attribute types with more than one attribute vector (e.g., texture
    coordinates, generic attributes).  For attribute types with only a single
    attribute, this element is ignored.  Otherwise, it identifies the specific
    attribute number.  The error INVALID_VALUE is generated if this element is
    greater than or equal to the number of attributes available for the
    specified type.

    Attribute type entries in <attribs> with the value NEXT_BUFFER_NV do not
    identify a vertex attribute, but instead serve as buffer separator values
    to direct subsequent attributes at the next transform feedback binding
    point.  Attribute type entries in <attribs> with the value
    SKIP_COMPONENTS1_NV, SKIP_COMPONENTS2_NV, SKIP_COMPONENTS3_NV, or
    SKIP_COMPONENTS4_NV also do not identify a specific vertex attribute type.
    These values are treated as requesting that the GL skip the next one to
    four components of attribute data.  Skipping components this way is
    equivalent to writing one to four components of undefined vertex attribute
    data, except that the corresponding memory in the buffer object is not
    modified.  Such array entries are counted as being written to the buffer
    object for the purposes of determining whether the requested attributes
    exceed per-buffer component count limits.  When an attribute type is
    NEXT_BUFFER_NV or of the form SKIP_COMPONENTS<n>_NV, the next two values
    in <attribs>, specifying component count and attribute number, are
    ignored.

    The error INVALID_OPERATION is generated if any such value is
    NEXT_BUFFER_NV, SKIP_COMPONENTS1_NV, SKIP_COMPONENTS2_NV,
    SKIP_COMPONENTS3_NV, or SKIP_COMPONENTS4_NV, and <bufferMode> is not
    INTERLEAVED_ATTRIBS.

                                permitted            GPU_program4
      attrib                    sizes     index?     result name
      ---------------------     --------  --------   --------------
      POSITION                  1,2,3,4     no       position
      PRIMARY_COLOR             1,2,3,4     no       color.front.primary
      SECONDARY_COLOR_NV        1,2,3,4     no       color.front.secondary
      BACK_PRIMARY_COLOR_NV     1,2,3,4     no       color.back.primary
      BACK_SECONDARY_COLOR_NV   1,2,3,4     no       color.back.secondary
      FOG_COORDINATE            1           no       fogcoord
      POINT_SIZE                1           no       pointsize
      TEXTURE_COORD_NV          1,2,3,4     yes      texcoord[index]
      CLIP_DISTANCE_NV          1           yes      clip[index]
      VERTEX_ID_NV              1           no       vertexid
      PRIMITIVE_ID_NV           1           no       primid
      GENERIC_ATTRIB_NV         1,2,3,4     yes      attrib[index]
      LAYER_NV                  1           no       layer
      NEXT_BUFFER_NV            0           no       ----
      SKIP_COMPONENTS1_NV       1           no       ----
      SKIP_COMPONENTS2_NV       2           no       ----
      SKIP_COMPONENTS3_NV       3           no       ----
      SKIP_COMPONENTS4_NV       4           no       ----

      Table X.1:  Transform Feedback Attribute Specifiers.  The "attrib"
      column specifies the attribute types available to record.  The
      "permitted sizes" column indicate the legal component count values for
      the attribute type.  The "index" column indicates if the attribute type
      has more than one attribute vector and requires an attribute number.
      The "GPU_program4 result name" column shows the suffix of the result
      variable binding recorded for each attribute type.

    The attributes captured by TransformFeedbackAttribsNV always come from
    primitives emitted to vertex stream zero.  However, the command

      void TransformFeedbackStreamAttribsNV(sizei count, const int * attribs, 
                                            sizei nbuffers, 
                                            const int *bufstreams, 
                                            enum bufferMode);

    can capture vertex attributes from arbitrary vertex streams.  <count>,
    <attribs>, and <bufferMode> operate as above.  <bufstreams> is an array of
    <nbuffers> vertex stream numbers used for each transform feedback binding
    point.  When a new primitive is emitted to a given vertex stream, vertex
    attributes are recorded only to those binding points whose corresponding
    <bufstreams> value equals the vertex stream number.  The error
    INVALID_VALUE is generated if any value in <bufstreams> is greater than or
    equal to the value of MAX_VERTEX_STREAMS.  The error INVALID_OPERATION is 
    generated if the number of binding points specified by <attribs> is not
    equal to <nbuffers>.  If <bufferMode> is INTERLEAVED_ATTRIBS, the
    number of binding points used is one plus the number of NEXT_BUFFER_NV
    values in <attribs>.  If <bufferMode> is SEPARATE_ATTRIBS, number of
    binding points used is given by <count>.

    The number of attributes or attribute components that may be recorded in
    transform feedback mode is limited.  The error INVALID_OPERATION is
    generated by TransformFeedbackAttribsNV or
    TransformFeedbackStreamAttribsNV if

      * <bufferMode> is SEPARATE_ATTRIBS, and <count> is greater than the
        limit MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_NV;

      * <bufferMode> is INTERLEAVED_ATTRIBS, and the total number of
        vertex components to record to any single binding point is greater
        than the limit MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_NV; or

      * <bufferMode> is INTERLEAVED_ATTRIBS, and the number of binding
        points used (one plus the number of NEXT_BUFFER_NV values in
        <attribs>) is greater than the limit
        MAX_TRANSFORM_FEEDBACK_BUFFERS.

    The set of attributes to record, set by TransformFeedbackAttribsNV or
    TransformFeedbackStreamAttribsNV, has no effect if a vertex or geometry
    shader is active.

    The value for any attribute specified to be recorded to a buffer object
    but not actually written by a vertex or geometry program is undefined.
    The value of PRIMITIVE_ID_NV or LAYER_NV for a vertex is defined if and
    only if a geometry program is active and that program writes to the result
    variable "result.primid".  The value of VERTEX_ID_NV is only defined if
    and only if a vertex program is active, no geometry program is active, and
    the vertex program writes to the output attribute "result.id".


    (Fold in corresponding language from NV_transform_feedback providing
     additional mechanisms for specifying the set of varyings or attributes to
     capture in transform feedback.  The only new functionality provided
     by this extension is the ability to provide separator values to write to
     multiple buffers in interleaved mode.)

    Additionally, it is also possible to change the set of varying variables
    to record in transform feedback mode immediately without relinking the
    program object.  The command

      void TransformFeedbackVaryingsNV(uint program, sizei count,
                                       const int *locations, 
                                       enum bufferMode)

    sets the transform feedback state for <program> and specifies the set of
    varying variables to record when transform feedback is active.
    <bufferMode> is either INTERLEAVED_ATTRIBS or SEPARATE_ATTRIBS and
    identifies the mode used to capture the varying variables when transform
    feedback is active.  The array <locations> contains <count> integers, each
    of which must be either a location of an active varying variable in
    <program> as queried with GetActiveVaryingNV() or one of the special
    values described below.

    If an entry in <locations> has the value NEXT_BUFFER_NV, it does not
    identify a varying variable.  Instead, it serves as a buffer separator
    value to direct subsequent varyings at the next transform feedback binding
    point.  If any entry is SKIP_COMPONENTS1_NV, SKIP_COMPONENTS2_NV,
    SKIP_COMPONENTS3_NV, or SKIP_COMPONENTS4_NV, it also does not identify a
    specific varying variable.  Instead, such values are treated as requesting
    that the GL skip the next one to four components of varying data.
    Skipping components this way is equivalent to specifying a one- to four-
    component varying with undefined values, except that the corresponding
    memory in the buffer object is not modified.  Such array entries are
    counted as being written to the buffer object for the purposes of
    determining whether the requested attributes exceed per-buffer component
    count limits.

    The error INVALID_VALUE is generated if <program> is not the name of a
    program object or if <bufferMode> is SEPARATE_ATTRIBS and <count> is
    greater than the limit MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS.  The
    error INVALID_OPERATION is generated:

      * if <program> has not been linked successfully;

      * if <program> is being used by any active transform feedback object;

      * if any value in <locations> is neither NEXT_BUFFER_NV nor the location
        of an active varying variable in <program>;

      * if any value in <locations> (other than NEXT_BUFFER_NV) appears more
        than once in the array;

      * if any value in <locations> is NEXT_BUFFER_NV, SKIP_COMPONENTS1_NV,
        SKIP_COMPONENTS2_NV, SKIP_COMPONENTS3_NV, or SKIP_COMPONENTS4_NV, and
        <bufferMode> is not INTERLEAVED_ATTRIBS;

      * if the number of NEXT_BUFFER_NV values in <locations> is greater
        than or equal to the value of MAX_TRANSFORM_FEEDBACK_BUFFERS;

      * <bufferMode> is SEPARATE_ATTRIBS and the total number of
        components to capture in any varying variable in <locations> is
        greater than the limit MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS;

      * <bufferMode> is INTERLEAVED_ATTRIBS, and the total number of
        vertex components to capture to any single binding point is greater
        than the limit MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS; or

      * the set of varyings to capture to any single binding point includes
        varyings from more than one vertex stream.

    The transform feedback state set by TransformFeedbackVaryingsNV
    immediately replaces any transform feedback varying state of <program>,
    whether the old state was set when <program> was last linked (using the
    varying names provided by TransformFeedbackVaryings), or via a
    post-link call to TransformFeedbackVaryingsNV.
    
    (Additions to Chapter 6 of the OpenGL 3.2 Specification (State and State
     Requests))
    
    (Clean up/replace the language added by NV_transform_feedback, which added
     a new Section 6.1.14 "Transform Feedback" and renamed 6.1.14 to 6.1.15.
     The only functional change here is to explicitly separator attributes
     provided for interleaved mode.)

    The set of vertex attributes to be recorded to a buffer object when
    neither a vertex nor geometry shader is active may be queried.  The buffer
    mode and number of attributes specified is obtained by calling GetIntegerv
    with <param> set to TRANSFORM_FEEDBACK_BUFFER_MODE_NV and
    TRANSFORM_FEEDBACK_ATTRIBS_NV, respectively.  Information on each
    individual attribute to record may be obtained by calling
    GetIntegerIndexedvEXT() with <param> set to TRANSFORM_FEEDBACK_RECORD_NV
    and <index> specifying the position of the attribute in the array given to
    TransformFeedbackAttribsNV.  Three integers will be returned, containing
    the three values passed to TransformFeedbackAttribsNV for the specified
    attribute.  The error INVALID_VALUE is generated if <index> is greater
    than or equal to the value of TRANSFORM_FEEDBACK_ATTRIBS_NV.  Any
    separators (NEXT_BUFFER_NV) passed to TransformFeedbackAttribsNV are
    counted as attributes for the purposes of these queries, and will be
    returned by TRANSFORM_FEEDBACK_RECORD_NV queries.
    
    (add to OpenGL 3.2 Section 6.1.10, Shader and Program Queries, p. 259)

    (Clean up/replace the language added to this section by
    NV_transform_feedback, and add language describing how separators are
    handled.)

    If <pname> is TRANSFORM_FEEDBACK_BUFFER_MODE, the buffer mode used when 
    transform feedback is active is returned.  If <pname> is
    TRANSFORM_FEEDBACK_VARYINGS, the number of varying variables to capture
    in transform feedback mode for the program is returned.  Any separators
    (NEXT_BUFFER_NV) provided to TransformFeedbackVaryingsNV count.  If
    <pname> is TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, the length of the
    longest varying name specified to be used for transform feedback,
    including a null terminator character, is returned.  If no varyings are
    used for transform feedback, zero is returned.

    The command

      void GetTransformFeedbackVaryingNV(uint program, uint index,
                                         int *location)

    returns the location of a varying variable to stream to a buffer object in
    <location>.  The array element numbered <index> in the array <locations>
    passed to TransformFeedbackVaryingsNV, is returned.  The error
    INVALID_VALUE is generated if <index> is greater than or equal to the
    value of TRANSFORM_FEEDBACK_VARYINGS_NV.  If <index> refers to a
    separator, the value NEXT_BUFFER_NV is returned.  The error
    INVALID_OPERATION is generated if <program> is not the name of a program
    object or if <program> has not been linked successfully.

    Modify section 5.4, Display Lists, p. 237

    On p. 358, add the following to the list of vertex buffer object commands
    not compiled into a display list: TransformFeedbackStreamAttribsNV.


Errors

    The error INVALID_VALUE is generated by BindBufferRange,
    BindBufferOffsetEXT, or BindBufferBase if <target> is
    TRANSFORM_FEEDBACK_BUFFER and <index> is greater than or equal to the
    value of MAX_TRANSFORM_FEEDBACK_BUFFERS.

    The error INVALID_VALUE is generated by BeginQueryIndexed, EndQueryIndexed
    or GetQueryIndexediv if <target> is TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN
    or PRIMITIVES_GENERATED and <index> is greater or equal to MAX_VERTEX_STREAMS.

    The error INVALID_OPERATION is generated by EndQueryIndexed if the active
    query object name at index <index> of target <target> is zero.

    The error INVALID_VALUE is generated by TransformFeedbackAttribsNV or
    TransformFeedbackStreamAttribsNV if the component count or attribute
    numbers specified in the <attribs> array are not consistent with the
    corresponding attribute type.

    The error INVALID_VALUE is generated by TransformFeedbackStreamAttribsNV
    if any value in <bufstreams> is greater than or equal to the value of
    MAX_VERTEX_STREAMS.

    The error INVALID_OPERATION is generated by TransformFeedbackStream-
    AttribsNV if the number of binding points specified by <attribs> is not
    equal to <nbuffers>.

    The error INVALID_OPERATION is generated by TransformFeedbackAttribsNV or
    TransformFeedbackStreamAttribsNV if

      * <bufferMode> is SEPARATE_ATTRIBS, and <count> is greater than the
        limit MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_NV;

      * <bufferMode> is INTERLEAVED_ATTRIBS, and the total number of
        vertex components to record to any single binding point is greater
        than the limit MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_NV;

      * <bufferMode> is INTERLEAVED_ATTRIBS, and the number of binding
        points used (one plus the number of NEXT_BUFFER_NV values in
        <attribs>) is greater than the limit
        MAX_TRANSFORM_FEEDBACK_BUFFERS; or

      * any attribute type value in <attribs> is NEXT_BUFFER_NV,
        SKIP_COMPONENTS1_NV, SKIP_COMPONENTS2_NV, SKIP_COMPONENTS3_NV, or
        SKIP_COMPONENTS4_NV, and <bufferMode> is not INTERLEAVED_ATTRIBS.

    The error INVALID_VALUE is generated by DrawTransformFeedbackStream
    if <stream> is greater than or equal to the value of 
    MAX_VERTEX_STREAMS.

    The error INVALID_VALUE is generated by TransformFeedbackVaryings if
    <program> is not the name of a program object, or if <bufferMode> is
    SEPARATE_ATTRIBS and <count> is greater than the limit
    MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS.

    The error INVALID_OPERATION is generated by TransformFeedbackVaryings
    if any pointer in <varyings> identifies the special names "gl_NextBuffer",
    "gl_SkipComponents1", "gl_SkipComponents2", "gl_SkipComponents3", or
    "gl_SkipComponents4" and <bufferMode> is not INTERLEAVED_ATTRIBS_NV, or if
    the number of "gl_NextBuffer" pointers in <varyings> is greater than or
    equal to the value of MAX_TRANSFORM_FEEDBACK_BUFFERS.

    The error INVALID_VALUE is generated by TransformFeedbackVaryingsNV if
    <program> is not the name of a program object, or if <bufferMode> is
    SEPARATE_ATTRIBS and <count> is greater than the limit
    MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS.

    The error INVALID_OPERATION is generated by TransformFeedbackVaryingsNV:

      * if <program> has not been linked successfully;

      * if <program> is being used by any active transform feedback object;

      * if any value in <locations> is neither NEXT_BUFFER_NV nor the location
        of an active varying variable in <program>;

      * if any value in <locations> (other than NEXT_BUFFER_NV) appears more
        than once in the array;

      * if any value in <locations> is NEXT_BUFFER_NV, SKIP_COMPONENTS1_NV,
        SKIP_COMPONENTS2_NV, SKIP_COMPONENTS3_NV, or SKIP_COMPONENTS4_NV, and
        <bufferMode> is not INTERLEAVED_ATTRIBS;

      * if the number of NEXT_BUFFER_NV values in <locations> is greater
        than or equal to the value of MAX_TRANSFORM_FEEDBACK_BUFFERS;

      * <bufferMode> is SEPARATE_ATTRIBS and the total number of
        components to capture in any varying variable in <locations> is
        greater than the limit MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS;

      * <bufferMode> is INTERLEAVED_ATTRIBS, and the total number of
        vertex components to capture to any single binding point is greater
        than the limit MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS; or

      * the set of varyings to capture to any single binding point includes
        varyings from more than one vertex stream.

    The error INVALID_VALUE is generated by GetIntegerIndexedvEXT if <param>
    is TRANSFORM_FEEDBACK_RECORD_NV and <index> is greater than or equal to
    the value of TRANSFORM_FEEDBACK_ATTRIBS_NV.

    The error INVALID_VALUE is generated by GetIntegerIndexedvEXT() if <param>
    is TRANSFORM_FEEDBACK_BUFFER_BINDING,
    TRANSFORM_FEEDBACK_BUFFER_START, or TRANSFORM_FEEDBACK_BUFFER_SIZE and 
    <index> is greater than or equal to the value of
    MAX_TRANSFORM_FEEDBACK_BUFFERS.

    The error INVALID_VALUE is generated by GetTransformFeedbackVaryingNV if
    <index> is greater than or equal to the value of
    TRANSFORM_FEEDBACK_VARYINGS_NV.

    The error INVALID_OPERATION is generated by GetTransformFeedbackVaryingNV
    if <program> is not the name of a program object, or if <program> has not
    been linked successfully.

    The error INVALID_ENUM is generated by BeginQuery if the <target> is
    PRIMITIVES_GENERATED<i>_NV or TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN<i>_NV
    and <i> is greater than or equal to the value of MAX_VERTEX_STREAMS.

New State

   (Modify Table 6.37, p 298, adding a variable number of new transform
   feedback query object binding points.)

    Get Value         Type  Get Command       Init. Value  Description                Sec    Attribute
    ----------------  ----  ----------------  -----------  -------------------------  -----  ---------
    CURRENT_QUERY     nxZ+  GetQueryiv        0            Active query object name   2.X        -
                                                           (occlusion, timer, per-
                                                           stream xform feedback)

New Implementation Dependent State

   (Add to the new table, Table 6.X. Transform Feedback State, previously
   added by EXT_transform_feedback.)

                                                  Minimum
    Get Value                  Type  Get Command   Value   Description                   Sec.  Attrib 
    ---------                  ----  -----------  -------  ---------------------------   ----  ------
    MAX_TRANSFORM_FEEDBACK_     Z+   GetIntegerv     4     Max number of buffer objs     2.Y     -
      BUFFERS                                              to write with xform feedback
    MAX_VERTEX_STREAMS          Z+   GetIntegerv     1     Maximum number of vertex      2.Y     -
                                                           streams supported

Issues

    (1) How should we provide the ability to record varyings/attributes to
        multiple buffers with multiple varyings/attributes per buffer?

      RESOLVED:  The version supported in the spec extends the interleaved
      mode provided by existing APIs to allow writing to multiple buffers.
      Special separator values are provided to allow the caller to direct
      subsequent varyings/attributes at the next buffer.  For example, the
      following code would capture the values of "batman" and "robin"
      interleaved to the first buffer binding point, and "riddler", "joker",
      and "manbearpig" interleaved to the second.  This example specifies
      attributes in the style used by EXT_transform_feedback (array of
      variable names set prior to linking).

        char *names[] = { "batman", "robin", "gl_NextBuffer",
                          "riddler", "joker", "manbearpig" };
        glTransformFeedbackVaryings(program, 6, names,
                                    GL_INTERLEAVED_ATTRIBS);

      The same example using the NV_transform_feedback-style API would
      produce:

        int locations[6] = {
          glGetVaryingLocation(program, "batman"),
          glGetVaryingLocation(program, "robin"),
          NEXT_BUFFER_NV,
          glGetVaryingLocation(program, "riddler"),
          glGetVaryingLocation(program, "joker"),
          glGetVaryingLocation(program, "manbearpig")
        };
        glTransformFeedbackVaryingsNV(program, 6, locations, 
                                      GL_INTERLEAVED_ATTRIBS);

      A similar example using assembly shaders might work like:

        int attribs[] = {
          GL_TEXTURE_COORD_NV, 3, 0,   // vec3 batman @ result.texcoord[0]
          GL_TEXTURE_COORD_NV, 3, 1,   // vec3 robin @ result.texcoord[1]
          NEXT_BUFFER_NV, 0, 0,
          GL_GENERIC_ATTRIB_NV, 4, 0,  // vec4 riddler @ result.attrib[0]
          GL_GENERIC_ATTRIB_NV, 2, 0,  // vec2 joker @ result.attrib[1]
          GL_GENERIC_ATTRIB_NV, 1, 0,  // float manbearpig @ result.attrib[2]
        };
        glTransformFeedbackAttribsNV(6, attribs, GL_INTERLEAVED_ATTRIBS);

      Another approach considered was to create a separate "mixed" mode enum,
      but to use separators and existing APIs.  That approach was close enough
      to the existing interleaved mode that we decided to use that instead.

      One alternate approach would avoid separators by providing a new "mixed
      mode" API entry point taking an array of pointers, where each points to
      an array of varying/attribute descriptors.

        char *heroes[] = { "batman", "robin" };
        char *villains[] = { "riddler", "joker", "manbearpig" };
        char **varyingLists[] = { heroes, villains };
        int varyingListLengths[] = { 2, 3 };
        glTransformFeedbackMixedVaryingsNV(program, 2, varyingListLengths,
                                           varyingLists);

    (2) How do multiple vertex streams work, and how do they work in
    conjunction with transform feedback?

     RESOLVED:  The NV_gpu_program5 and ARB_gpu_shader5 extensions
     introduce the notion of multiple vertex streams emitted in geometry
     shaders.  The following figure is a simplified picture of the vertex
     processing pipeline.

                |
                | vertices in
                V
              vertex
              shader
                |
                V
             primitive
             assembly
                |
                +-----------+
                |           |
                |      tessellation
                |           |
                +<----------+
                |        
                +---------------+
                |               |
                |stream         V
                |0           geometry
                |             shader
                |            | | | |
                |            V V V V
                |            primitive
                |            assembly
                V            | | | |
                +------------+ | | |
                |  stream 0    | | |
                |              | | |
                |  +-----------+ | |
                |  |stream 1     | |
                |  |             | |
                |  |     stream 2| |stream 3
                |  |  +----------+ |
                |  |  |  +---------+
                |  |  |  |
                V  V  V  V
            transform feedback ----+--------> binding point 0 ----> buffer
                |                  +--------> binding point 1 ----> buffer
                | stream 0         +--------> binding point 2 ----> buffer
                +---+              +--------> binding point 3 ----> buffer
                    |
                    V
                clipping,
               rasterization,
                  etc...

     Vertices are initially received via commands such as glDrawArrays,
     glDrawElements, glArrayElement, or glVertex.  Vertices are first 
     processed by the vertex shader and/or the fixed-function vertex pipeline
     and are assembled into primitives (points, lines, triangles, etc...).  If
     tessellation shaders are enabled, these primitives are processed by the
     programmable shaders and associated fixed-function hardware and are
     assembled into primitives.  Each primitive assembled after vertex
     shading and tessellation is said to belong to vertex stream 0, which is
     effectively the only vertex stream supported by the GL prior to this
     extension.

     If a geometry shader is enabled, it is run on each input primitive in
     vertex stream 0.  Such primitives are consumed by the geometry shader.
     However, the geometry shader can emit new vertices, and each vertex
     emitted is directed at a specified vertex stream.  The geometry shader
     has an effective output primitive type for each vertex stream used to
     assemble the emitted vertices into primitives.  In the initial
     implementation of this extension, four such streams are supported, and
     only the POINTS output primitive type is supported if more than one
     stream is used.  When a sufficient number of vertices are emitted to a
     stream, the primitive assembly stage below the geometry shader sends the
     corresponding primitive down the appropriate primitive stream.  If
     geometry shaders are disabled, all primitives assembled by previous
     stages remain on stream 0.

     The primitives on all streams are seen by the transform feedback stage.
     As each primitive is received on any vertex stream, the transform
     feedback stage checks the set of varyings/attributes selected for each
     binding point.  If they don't belong to the vertex stream the primitive
     came from, nothing is written to buffer attached to the binding point.
     Otherwise, transform feedbacks loops first over the vertices in the
     primitive and then the varyings/attributes used for the binding point,
     writing each selected value to the attached buffer object.  The API
     doesn't allow a single binding point to store variables from more than
     one vertex stream, so each binding point effectively has an associated
     vertex stream it reads from.

     After transform feedback, the primitives from stream zero are passed to
     subsequent primitive processing stages (flat shading/color selection,
     clipping, rasterization); primitives on all other streams are discarded.

    (3) How might you use transform feedback with geometry shaders and
        multiple vertex streams?

      RESOLVED:  As a simple example, let's say you are processing triangles
      and capture both processed triangle vertices and some values that are
      computed per-primitive (e.g., facet normal).  The geometry shader
      might declare its outputs like the following:
      
        layout(stream = 0) out vec4 position;
        layout(stream = 0) out vec4 texcoord;
        layout(stream = 1) out vec4 normal;

      "position" and "texcoord" would be per-vertex attributes written to
      vertex stream 0; "normal" would be a per-triangle facet normal.  The
      geometry shader would emit three vertices to stream zero (the processed
      input vertices) and a single vertex to stream one (the per-triangle
      data).  The transform feedback API usage for this case would be
      something like:

        // Set up buffer objects 21 and 22 to capture data for per-vertex and
        // per primitive values.
        glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 21);
        glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 1, 22);

        // Set up XFB to capture position and texcoord to buffer binding 
        // point 0 (buffer 21 bound), and normal to binding point 1 (buffer 
        // 22 bound).
        char *strings[] = { "position", "texcoord", "gl_NextBuffer", 
                            "normal" };
        // create <program>
        glTransformFeedbackVaryings(program, 4, strings, 
                                    GL_INTERLEAVED_ATTRIBS);
        // link <program>

      A setup like:

        char *strings[] = { "position", "gl_NextBuffer", 
                            "texcoord", "gl_NextBuffer", "normal" };

      would capture "position" to binding point 0, "normal" to binding point
      1, and "texcoord" to binding point 2.  When a vertex is emitted to
      vertex stream 0, transform feedback would write to the first two binding
      points, but not the third.  When per-primitive data is emitted to vertex
      stream 1, transform feedback would write to the third binding point,
      but not the first two.

      A setup like:

        char *strings[] = { "position", "normal", "gl_NextBuffer", 
                            "texcoord" };

      would be illegal (LinkProgram would fail) because the first binding
      point would want to capture varyings from both vertex streams.      

    (4) With multiple vertex streams supported by geometry shaders, the number
        of primitives generated and/or written by transform feedback is
        different for each stream.  How should we expose the ability to query
        these counts?

      RESOLVED:  The set of primitive query object targets
      (PRIMITIVES_GENERATED and TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN)
      is extended to contain a target for each vertex stream.  The new
      query targets PRIMITIVES_GENERATED<n> and
      TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN<n> are provided to select the
      stream number to use for a query object.  To simultaneously determine
      the number of primitives written to multiple vertex streams, multiple
      query objects should be used.  For example:

        glBeginQuery(GL_PRIMITIVES_GENERATED0, 11);
        glBeginQuery(GL_PRIMITIVES_GENERATED1, 12);
        draw_some_stuff();
        glEndQuery(GL_PRIMITIVES_GENERATED0);
        glEndQuery(GL_PRIMITIVES_GENERATED1);

      will record the number of primitives generated on vertex stream zero by
      "draw_some_stuff()" to query object 11 and the number of primitives
      generated on vertex stream one to query object 12.

      Two other API choices were considered but rejected.  One choice was to
      define a query target to have multiple query object attachment points
      (one for each vertex stream).  This would require adding
      BeginQueryIndexedNV, EndQueryIndexedNV, and GetQueryIndexedNV functions,
      and modifying all the existing query language to allow for this
      possibility.  We chose instead to replicate enumerants to avoid adding
      the new API and spec language.  We expect that 8 streams should be
      sufficient.

      A second choice was to extend the result values of the existing
      primitive query objects from a single integer to an <n>-component
      vector, where <n> is the total number of vertex streams supported.  New
      query object mechanisms could be provided to query an individual element
      in that vector.  It might have been possible to define the existing
      query to return the entire vector integer at once, but that could be a
      problem for applications that used the old API on new hardware and
      allocated space for only a single integer in its return buffer.

    (5) How do the EXT- and NV-style transform feedback APIs interact with
        each other?

      RESOLVED:  The EXT-style API requires that you provide a list of
      varyings prior to linking a program object, and does not provide the
      ability to change the set without re-linking.  With the NV-style API,
      the set of varyings to record is cleared when the program is linked,
      but you can re-specify the set of varyings to record multiple times
      after linking without any re-link.

      Fortunately, the two APIs fit together nicely.  When both extensions are
      supported, the state set by EXT is defined to specify the values to
      capture when the program is next linked.  If no variables are set using
      the EXT-style API, the transform feedback state is reset on a link, as
      called for by the NV-style API.  After linking, the NV-style API can be
      used to change the variables to capture, and such changes don't collide
      with any EXT-style state changes, which would require a re-link to take
      effect.

    (6) What value should we use when defining the separator token for
        NV-style transform feedback APIs?

      RESOLVED:  Unlike most existing GL defines, as we've chosen the value
      "-2".  Both the GLSL and assembly NV-style APIs take arrays of signed
      integers.  For the GLSL API, array entries are integers.  By convention,
      the "location" an invalid variable name is "-1", with valid locations
      returned as non-negative integers.  For the assembly-style API, the
      attribute types are just numbers, with nothing requiring that the number
      be positive or negative.  The choice of "-2" can be used for both API
      styles, and guarantees that the separator separator will not collide
      with a valid GLSL varying location or the "invalid varying" marker of
      -1.

    (7) How do multiple vertex streams interact with the
        DrawTransformFeedback() API added by the ARB_transform_feedback2
        extension?

      RESOLVED:  Prior to this extension, there was only one vertex stream,
      so the vertex count to be used by DrawTransformFeedback() was
      unambiguous.  With multiple streams, there may be different vertex
      counts written to each buffer.  We will add a new
      DrawTransformFeedbackStream command to draw using the number of
      vertices recorded to buffers for the specified vertex stream during the
      last transform feedback operation.  The existing DrawTransformFeedback
      command is defined to use the number of vertices recorded to buffers for
      vertex stream zero.

      We chose an API that makes the vertex counts for all streams used by a
      transform feedback object available for DrawTransformFeedback
      operations.  We also considered an API that would have required the user
      to select a single stream prior to calling BeginTransformFeedback,
      where only the vertex count from that stream would be available for
      subsequent operations.  We decided that there might be a usage case for
      an application that sorted its vertices into multiple streams, but still
      wanted to draw them all in a subsequent pass.  To do this, all vertex
      counts would have to be made available.

    (8) What happens with the DrawTransformFeedback() API if no complete
        primitives were emitted to the selected stream?  What if complete
        primitives were emitted to the stream but no varyings from that stream
        were selected for transform feedback?

      RESOLVED:  The vertex count used by DrawTransformFeedbackNV() is the
      number of vertices recorded from the selected stream.  If no primitives
      are emitted to that stream, the vertex count will be zero.  If the set
      of varyings selected for transform feedback does not include any
      belonging to the specified stream, nothing will be recorded when
      primitives are emitted to that stream, and the corresponding vertex
      count will be zero.

    (9) The new extension to interleaved mode provides increased flexibility
        on how varyings or attributes can be assigned to individual buffers
        for transform feedback.  How can you query which varying/attribute is
        assigned to which buffer?

      RESOLVED:  The transform feedback attribute enumeration/query
      functions will return separator values in the positions where they were
      originally provided.  An application can figure out the buffer a varying
      goes to by counting the number of separators prior to an attribute.  It
      would be possible to provide a utility API that says "give me the <n>th
      varying recorded to binding point <m>", but simply returning separators
      seems usable enough.

    (10) Previous transform feedback specs disallowed recording the same
         varying/attribute more than once.  Should we continue that
         restriction?  In particular, this may be problematic for assembly
         shaders using multiple vertex streams that wish to use the same
         attribute locations in multiple streams.

      RESOLVED:  We should probably allow recording the same attribute more
      than once in some form, if for no other reason than to handle the
      multi-stream assembly case described in the question. Resolved by 
      allowing this for TransformFeedbackStreamAttribsNV.

    (11) Should we provide the ability to leave holes in the data emitted by
         transform feedback?  This would provide applications the ability to
         combine captured vertex attributes of multiple passes into a single
         buffer object.

      RESOLVED:  Yes.  This spec extended the separator notion added to
      write to multiple buffers included in interleaved mode to include
      special "spacer" markers (e.g., "skip 4 components") as well.  Consider
      the following example in the EXT_transform_feedback API:

        char *names[] = { "batman", "gl_SkipComponents3", "robin", 
                          "gl_NextBuffer", "riddler", "gl_SkipComponents2", 
                          "joker", "manbearpig" };
        glTransformFeedbackVaryings(program, 8, names,
                                    GL_INTERLEAVED_ATTRIBS);

      "gl_SkipComponents<N>" is a special marker to indicate that <N> words
      should be skipped when recording values.  In this case, each vertex
      written to the first binding point would start with the value of
      "batman", then leave 3 components worth of data unmodified, and then
      finish with the value of "robin".

      For the NV_transform_feedback APIs, the special values
      GL_SKIP_COMPONENTS1_NV through GL_SKIP_COMPONENTS4_NV are provided.  We
      chose to provide four tokens even for the assembly API, which could have
      used a GL_SKIP_COMPONENTS_NV token with a separate count value
      containing 1-4.  However, the GLSL-based API needs separate tokens
      because there is no way to pass a component count separately.  We
      decided to use the same tokens for both APIs to minimize confusion.

    (12) Now that you can write to more than one buffer, what does
         MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS now mean?

      RESOLVED:  This query will return the number of components that may be
      written to a single buffer in interleaved mode.  Since interleaved mode
      now supports multiple buffers, the total number of components that may
      be written in the single pass is the product of this per-buffer limit
      and the number of buffers that may be written at once.

      The state table entry in the EXT_transform_feedback specification
      actually defined it this way, using the language "max number of
      components write to a single buffer in interleaved mode."

    (13) How does rasterization work when vertices may be emitted to multiple
         streams?

      RESOLVED:  Primitives sent to stream zero are the only ones rasterized.
      When primitives are received on any other streams, they are discarded
      after any transform feedback operations involving that stream are
      completed.
      
      When using GLSL geometry shaders, stream zero is the only one that
      makes sense for rasterization, because the geometry shader output
      "gl_Position" is associated with stream zero.

      We considered building a mechanism for rasterization to select from any
      of the vertex streams, but decided not to include such a feature since
      it would require some way to designate a position for each stream or
      potentially assign "gl_Position" to all streams.

    (15) How might you use transform feedback with assembly geometry programs
         and multiple vertex streams?

      RESOLVED:  As in issue (3), let's say you are processing triangles and
      capture both processed triangle vertices and some values that are
      computed per-primitive (e.g., facet normal).  The geometry program might
      declare outputs like the following:
      
        RESULT position = result.position;          # used in stream 0
        RESULT texcoord = result.texcoord[0];       # used in stream 0
        RESULT normal = result.texcoord[0];         # used in stream 1

      "position" and "texcoord" would be per-vertex attributes written to
      vertex stream 0; "normal" would be a per-triangle facet normal.  The
      geometry program would emit three vertices to stream zero (the processed
      input vertices) and a single vertex to stream one (the per-triangle
      data).  The transform feedback API usage for this case would be:

        int attribs[] = {
          GL_TEXTURE_COORD_NV, 3, 0,   // vec3 normal @ result.texcoord[0]
          NEXT_BUFFER_NV, 0, 0,
          GL_POSITION,         4, 0,   // vec4 position @ result.position
          GL_TEXTURE_COORD_NV, 2, 0,   // vec2 texcoord @ result.texcoord[0]
        };
        int streams[] = { 1, 0 };
        glTransformFeedbackStreamAttribsNV(3, attribs, 2, streams,
                                           GL_INTERLEAVED_ATTRIBS);

      streams[0] is 1, which means that only the vertices emitted to stream
      one will be written to the first binding point (where "normal" goes).
      streams[1] is 0, which means that only the vertices emitted to stream
      zero will be written to the second binding point (where "position" and
      "texcoord" go).

    (17) How does this extension interact with the old-school feedback and
         select modes set by glRenderMode?

      RESOLVED:  This spec provides multiple vertex streams, where only
      stream 0 is sent to the rasterizer.  Feedback and select modes will
      only operate on primitives sent to the stream 0.  Primitives sent to
      other streams are ignored, after they are optionally captured in
      transform feedback mode.

    (18) How do transform feedback vertex streams interact with separate
         shader objects (EXT_separate_shader_objects)?

      RESOLVED:  The data captured in transform feedback are produced by the
      last active shader stage prior to the transform feedback stage.  If
      there is an active program object for the geometry shader stage, and
      that program has a geometry shader that emits vertices to multiple
      streams, such a configuration behaves exactly like a similar
      configuration using a single program object.


Revision History

    Rev.    Date     Author    Changes
    ----  --------   --------  -----------------------------------------
    12    03/23/2010 pbrown    Update issue (13) and add issue (18) from
                               issues left behind in the NV_gpu_shader5 when
                               specs were refactored.

    11    02/04/2010 gsellers  Add indexed query entry points.
                               Remove indexed enums.

    10    02/02/2010 pbrown    Clarify that "gl_SkipComponents*" is in
                               units of "float" (bug 5863).

     9    01/20/2010 pbrown    Update extension interaction references 
                               to use ARB_gpu_shader5 (instead of "EXT").

     8    01/14/2010 Jon Leech Update errors for out of range vertex 
                               streams passed to
                               DrawTransformFeedbackStream and
                               BeginQuery to match core specification 
                               (Bug 5896).

     7    12/07/2009 jbolz     Rename EXT->ARB.

     6    10/22/2009 jbolz     Close unresolved issues, with no functional
                               changes.

     5    10/22/2009 jbolz     Incorporated fixes from bmerry. Changed 
                               GetTransformFeedbackVarying to not return
                               length=0 for separators.

     4    09/30/2009 pbrown    Removed tessellation shader dependencies,
                               including language describing capture of
                               patches.  Capture of patches will only be
                               supported via NV_gpu_shader5.

     3    09/17/2009 pdaniell  Move PATCHES_EXT into NV dependencies.
                               Remove VertexDrawStreamEXT as only stream 0
                               is output to the rasterizer.

     2    09/14/2009 pdaniell  EXTify. Move NV stuff into dependencies.

     1               pbrown    Internal revisions.

