Name

    EXT_transform_feedback

Name Strings

    GL_EXT_transform_feedback

Contributors

    Nick Carter
    Charlie Lao
    Jeremy Sandmel
    Cliff Woolley
    Alex Eddy

Contact

    Barthold Lichtenbelt (blichtenbelt 'at' nvidia.com)
    Pat Brown (pbrown 'at' nvidia.com)
    Eric Werness (ewerness 'at' nvidia.com)

Status

    Shipping.

Version

    Last Modified Date:         08/09/2013
    NVIDIA Revision:            8

Number

    352

Dependencies

    The OpenGL Shading Language (GLSL) is required.  OpenGL 2.0 or the
    ARB_shader_objects extension is required.

    EXT_geometry_shader4 trivially interacts with this extension.

    NV_transform_feedback interacts with this extension.

    This extension is written against the OpenGL 2.0 specification.

Overview

    This extension provides a new mode to the GL, called transform feedback,
    which records selected vertex attributes for each primitive processed by
    the GL.  The selected attributes are written into buffer objects, and can
    be written with each attribute in a separate buffer object or with all
    attributes interleaved into a single buffer object.  If a geometry shader
    is active, the primitives recorded are those emitted by the geometry
    shader.  Otherwise, transform feedback captures primitives whose vertices
    are transformed by a vertex shader.  In either case, the primitives
    captured are those generated prior to clipping.  Transform feedback mode
    captures the values of specified varying variables emitted from GLSL
    vertex or geometry shaders.

    The vertex data recorded in transform feedback mode is stored into buffer
    objects as an array of vertex attributes.  The regular representation and
    the use of buffer objects allows the recorded data to be processed
    directly by the GL without requiring CPU intervention to copy data.  In
    particular, transform feedback data can be used for vertex arrays (via
    vertex buffer objects), as the source for pixel data (via pixel buffer
    objects), as shader constant data (via the NV_parameter_buffer_object or
    EXT_bindable_uniform extensions), or via any other extension that makes
    use of buffer objects.

    This extension introduces new query object support to allow transform
    feedback mode to operate asynchronously.  Query objects allow applications
    to determine when transform feedback results are complete, as well as the
    number of primitives processed and written back to buffer objects while in
    transform feedback mode.  This extension also provides a new rasterizer
    discard enable, which allows applications to use transform feedback to
    capture vertex attributes without rendering anything.

New Procedures and Functions

    void BindBufferRangeEXT(enum target, uint index, uint buffer,
                           intptr offset, sizeiptr size);
    void BindBufferOffsetEXT(enum target, uint index, uint buffer,
                            intptr offset);
    void BindBufferBaseEXT(enum target, uint index, uint buffer);

    void BeginTransformFeedbackEXT(enum primitiveMode);
    void EndTransformFeedbackEXT(void);

    void TransformFeedbackVaryingsEXT(uint program, sizei count,
                                      const char * const *varyings, 
                                      enum bufferMode);
    void GetTransformFeedbackVaryingEXT(uint program, uint index,
                                        sizei bufSize, sizei *length, 
                                        sizei *size, enum *type, char *name);

    void GetIntegerIndexedvEXT(enum param, uint index, int *values);
    void GetBooleanIndexedvEXT(enum param, uint index, boolean *values);

    (Note: These indexed query functions are provided in the EXT_draw_buffers2
    extension.  The boolean query is not useful for any queryable value in
    this extension, but is supported for completeness and consistency with
    base GL typed "Get" functions.)

New Tokens

    Accepted by the <target> parameters of BindBuffer, BufferData,
    BufferSubData, MapBuffer, UnmapBuffer, GetBufferSubData,
    GetBufferPointerv, BindBufferRangeEXT, BindBufferOffsetEXT and
    BindBufferBaseEXT:

      TRANSFORM_FEEDBACK_BUFFER_EXT                     0x8C8E

    Accepted by the <param> parameter of GetIntegerIndexedvEXT and
    GetBooleanIndexedvEXT:

      TRANSFORM_FEEDBACK_BUFFER_START_EXT               0x8C84
      TRANSFORM_FEEDBACK_BUFFER_SIZE_EXT                0x8C85

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

      TRANSFORM_FEEDBACK_BUFFER_BINDING_EXT             0x8C8F

    Accepted by the <bufferMode> parameter of TransformFeedbackVaryingsEXT:

      INTERLEAVED_ATTRIBS_EXT                           0x8C8C
      SEPARATE_ATTRIBS_EXT                              0x8C8D

    Accepted by the <target> parameter of BeginQuery, EndQuery, and
    GetQueryiv:

      PRIMITIVES_GENERATED_EXT                          0x8C87
      TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_EXT         0x8C88

    Accepted by the <cap> parameter of Enable, Disable, and IsEnabled, and by
    the <pname> parameter of GetBooleanv, GetIntegerv, GetFloatv, and
    GetDoublev:

      RASTERIZER_DISCARD_EXT                            0x8C89

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

      MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT 0x8C8A
      MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_EXT       0x8C8B
      MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_EXT    0x8C80

   Accepted by the <pname> parameter of GetProgramiv:

      TRANSFORM_FEEDBACK_VARYINGS_EXT                   0x8C83
      TRANSFORM_FEEDBACK_BUFFER_MODE_EXT                0x8C7F
      TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH_EXT         0x8C76


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

    Insert three new sections between Sections 2.11, Coordinate Transforms and
    2.12, Clipping:

    (Move the "Asynchronous Queries" language out of Section 4.1.7.  This
    section doesn't really introduce any new functionality, other than
    alluding to the transform feedback queries introduced below.)

    Section 2.X, Asynchronous Queries

    Asynchronous queries provide a mechanism to return information about the
    processing of a sequence of GL commands.  There are two query types
    supported by the GL.  Transform feedback queries (section 2.Y) returns
    information on the number of vertices and primitives processed by the GL
    and written to one or more buffer objects.  Occlusion queries (section
    4.1.7.1) count the number of fragments or samples that pass the depth
    test.

    The results of asynchronous queries are not returned by the GL immediately
    after the completion of the last command in the set; subsequent commands
    can be processed while the query results are not complete.  When
    available, the query results are stored in an associated query object.
    The commands described in section 6.1.12 provide mechanisms to determine
    when query results are available and return the actual results of the
    query.  The name space for query objects is the unsigned integers, with
    zero reserved by the GL.

    Each type of query supported by the GL has an active query object name. If
    the active query object name for a query type is non-zero, the GL is
    currently tracking the information corresponding to that query type and
    the query results will be written into the corresponding query object.  If
    the active query object for a query type name is zero, no such information
    is being tracked.

    A query object is created by calling

      void BeginQuery(enum target, uint id);

    with an unused name <id>.  <target> indicates the type of query to be
    performed; valid values of <target> are defined in subsequent
    sections. When a query object is created, the name <id> is marked as used
    and associated with a new query object.

    BeginQuery sets the active query object name for the query type given by
    <target> to <id>.  If BeginQuery is called with an <id> of zero, if the
    active query object name for <target> is non-zero, or if <id> is the
    active query object name for any query type, the error INVALID OPERATION
    is generated.

    The command

      void EndQuery(enum target);

    marks the end of the sequence of commands to be tracked for the query type
    given by <target>.  The active query object for <target> is updated to
    indicate that query results are not available, and the active query object
    name for <target> is reset to zero.  When the commands issued prior to
    EndQuery have completed and a final query result is available, the query
    object, active when EndQuery is, called is updated by the GL.  The query
    object is updated to indicate that the query results are available and to
    contain the query result.  If the active query object name for <target> is
    zero when EndQuery is called, the error INVALID_OPERATION is generated.

   The command

      void GenQueries(sizei n, uint *ids);

    returns <n> previously unused query object names in <ids>. These names are
    marked as used, but no object is associated with them until the first time
    they are used by BeginQuery.

    Query objects are deleted by calling

      void DeleteQueries(sizei n, const uint *ids);

    <ids> contains <n> names of query objects to be deleted. After a query
    object is deleted, its name is again unused.  Unused names in <ids> are
    silently ignored.

    Calling either GenQueries or DeleteQueries while any query of any target
    is active causes an INVALID_OPERATION error to be generated.

    Query objects contain two pieces of state:  a single bit indicating
    whether a query result is available, and an integer containing the query
    result value.  The number of bits used to represent the query result is
    implementation-dependent.  In the initial state of a query object, the
    result is available and its value is zero.

    The necessary state for each query type is an unsigned integer holding the
    active query object name (zero if no query object is active), and any
    state necessary to keep the current results of an asynchronous query in
    progress.

    Section 2.Y, Transform Feedback

    In transform feedback mode, attributes of the vertices of transformed
    primitives processed by a vertex or geometry shader are written out to one
    or more buffer objects.  The vertices are fed back after vertex color
    clamping, but before clipping.  If a geometry shader is active, the
    vertices recorded are those emitted from the geometry shader.  The
    transformed vertices may be optionally discarded after being stored into
    one or more buffer objects, or they can be passed on down to the clipping
    stage for further processing.  The set of attributes captured is
    determined when a program is linked.

    Transform feedback is started and finished by calling

      void BeginTransformFeedbackEXT(enum primitiveMode)

    and

      void EndTransformFeedbackEXT(void),

    respectively. Transform feedback is said to be active after a call to
    BeginTransformFeedbackEXT and inactive after a call to
    EndTransformFeedbackEXT.  <primitiveMode> is one of TRIANGLES, LINES, or
    POINTS, and specifies the output type of primitives that will be recorded
    into the buffer objects bound for transform feedback (see
    below). <primitiveMode> places a restriction on the primitive types that
    may be rendered while transform feedback is active -- see table X.1.

      Transform Feedback
      primitiveMode               allowed render primitive modes
      ----------------------      ---------------------------------
      POINTS                      POINTS
      LINES                       LINES, LINE_LOOP, and LINE_STRIP
      TRIANGLES                   TRIANGLES, TRIANGLE_STRIP,
                                  TRIANGLE_FAN, QUADS, QUAD_STRIP,
                                  and POLYGON

    Table X.1 Legal combinations between the transform feedback primitive
    mode, as passed to BeginTransformFeedbackEXT and the current primitive
    mode.

    Transform feedback commands must be paired; the error INVALID_OPERATION is
    generated by BeginTransformFeedbackEXT if transform feedback is active,
    and by EndTransformFeedbackEXT if transform feedback is inactive.

    Transform feedback mode captures the values of varying variables written
    by an active vertex or geometry shader.  The error INVALID_OPERATION is
    generated by BeginTransformFeedbackEXT if no vertex or geometry shader is
    not active.

    When transform feedback is active, all geometric primitives generated must
    be compatible with the value of <primitiveMode> passed to
    BeginTransformFeedbackEXT.  The error INVALID_OPERATION is generated by
    Begin or any operation that implicitly calls Begin (such as DrawElements)
    if <mode> is not one of the allowed modes in Table X.1.  If a geometry
    shader is active, its output primtive type is used instead of the <mode>
    parameter passed to Begin for the purposes of this error check.

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

      void BindBufferRangeEXT(enum target, uint index, uint buffer,
                              intptr offset, sizeiptr size)
      void BindBufferOffsetEXT(enum target, uint index, uint buffer,
                               intptr offset)
      void BindBufferBaseEXT(enum target, uint index, uint buffer)

    with <target> set to TRANSFORM_FEEDBACK_BUFFER_EXT.  There is an array of
    buffer object binding points that are used while transform feedback is
    active, plus a single general binding point that can be used by other
    buffer object manipulation functions (e.g., BindBuffer, MapBuffer).  All
    three commands bind the buffer object named by <buffer> to the general
    binding point, and additionally bind the buffer object to the binding
    point in the array given by <index>.  The error INVALID_VALUE is generated
    if <index> is greater than or equal to the value of
    MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_EXT.

    For BindBufferRangeEXT, <offset> specifies a starting offset into the
    buffer object <buffer> and <size> specifies the amount of data that can be
    written to the buffer object while transform feedback mode is active.
    Both <offset> and <size> are in basic machine units.  The error
    INVALID_VALUE is generated if the value of <size> is less than or equal to
    zero, or if either <offset> or <size> are not word-aligned.  Calling
    BindBufferOffsetEXT is equivalent of calling BindBufferRangeEXT with
    <size> = sizeof(buffer) - <offset>, and rounding <size> down so that it is
    word-aligned. BindBufferBaseEXT is equivalent to calling
    BindBufferOffsetEXT with an <offset> of 0.

    When an individual point, line, or triangle primitive reaches the
    transform feedback stage while transform feedback is active, the values of
    the specified varying variables of the vertex are appended to the buffer
    objects bound to the transform feedback binding points.  The attributes of
    the first vertex received after BeginTransformFeedbackEXT are written at
    the starting offsets of the bound buffer objects set by
    BindBufferRangeEXT, and subsequent vertex attributes are appended to the
    buffer object.  When capturing line and triangle primitives, all
    attributes of the first vertex are written first, followed by attributes
    of the subsequent vertices.  When writing varying variables that are
    arrays, individual array elements are written in order.  For
    multi-component varying variables or varying array elements, the
    individual components are written in order.  The value for any attribute
    specified to be streamed to a buffer object but not actually written by a
    vertex or geometry shader is undefined.

    When quads and polygons are provided to transform feedback with a
    primitive mode of TRIANGLES, they will be tessellated and recorded as
    triangles (the order of tessellation within a primitive is undefined).
    Individual lines or triangles of a strip or fan primitive will be
    extracted and recorded separately. Incomplete primitives are not recorded.

    Transform feedback can operate in either INTERLEAVED_ATTRIBS_EXT or
    SEPARATE_ATTRIBS_EXT mode.  In INTERLEAVED_ATTRIBS_EXT mode, the values of
    one or more varyings are written, interleaved, into the buffer object
    bound to the first transform feedback binding point (index = 0).  If more
    than one varying variable is written, they will be recorded in the order
    specified by TransformFeedbackVaryingsEXT (section 2.15.3).  In
    SEPARATE_ATTRIBS_EXT mode, the first varying variable specified by
    TransformFeedbackVaryingsEXT is written to the first transform feedback
    binding point; subsequent varying variables are written to the subsequent
    transform feedback binding points.  The total number of variables that may
    be captured in separate mode is given by
    MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_EXT.

    If recording the vertices of a primitive to the buffer objects being used
    for transform feedback purposes would result in either exceeding the
    limits of any buffer object's size, or in exceeding the end position
    <offset> + <size> - 1, as set by BindBufferRangeEXT, then no vertices of
    that primitive are recorded in any buffer object, and the counter
    corresponding to the asynchronous query target
    TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_EXT (see Section 2.Z) is not
    incremented.

    In either separate or interleaved modes, all transform feedback binding
    points that will be written to must have buffer objects bound when
    BeginTransformFeedbackEXT is called.  The error INVALID_OPERATION is
    generated by BeginTransformFeedbackEXT if any binding point used in
    transform feedback mode does not have a buffer object bound.  In
    interleaved mode, only the first buffer object binding point is ever
    written to.  The error INVALID_OPERATION is also generated by
    BeginTransformFeedbackEXT if no binding points would be used, either
    because no program object is active or because the active program object
    has specified no varying variables to record.

    While transform feedback is active, the set of attached buffer objects and
    the set of varying variables captured may not be changed.  If transform
    feedback is active, the error INVALID_OPERATION is generated by
    UseProgram, by LinkProgram if <program> is the currently active program
    object, and by BindBufferRangeEXT, BindBufferOffsetEXT, or
    BindBufferBaseEXT if <target> is TRANSFORM_FEEDBACK_BUFFER_EXT.


    Section 2.Z, Primitive Queries
 
    Primitive queries use query objects to track the number of primitives
    generated by the GL and to track the number of primitives written to
    transform feedback buffers.

    When BeginQuery is called with a <target> of PRIMITIVES_GENERATED_EXT, the
    primitives-generated count maintained by the GL is set to zero. When the
    generated primitive query is active, the primitives-generated count is
    incremented every time a primitive reaches the Discarding Rasterization
    stage (see Section 3.x) right before rasterization. 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 BeginQuery is called with a <target> of
    TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_EXT, the transform-feedback-
    primitives-written count maintained by the GL is set to zero. When the
    transform feedback primitive written query is active, the
    transform-feedback-primitives-written count is incremented every time a
    primitive is recorded into a buffer object. If transform feedback is not
    active, this counter is not incremented. If the primitive does not fit in
    the buffer object, the counter is not incremented.

    These two queries can be used together to determine if all primitives 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, the buffer is full.


    Modify Section 2.15.3 "Shader Variables", p. 75.

    Change the second sentence in the first paragraph on p. 84 as follows:

    . . . written by a vertex shader, read by a fragment shader, or used for
    transform feedback will count against this limit.  The transformed vertex
    position (gl_Position) does not count against this limit. ...

    Add the following language to the end of section 2.15.3 (p.84):

    Each program object can specify one or more varying variables to be
    recorded in transform feedback mode.  This set is specified by the command

      void TransformFeedbackVaryingsEXT(uint program, sizei count,
                                        const char * const *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.  The varying variables specified
    in <varyings> can be either built-in varying variables (beginning with
    "gl_") or user-defined ones. varying variables are written out in the
    order they appear in the array <varyings>. <bufferMode> is either
    INTERLEAVED_ATTRIBS_EXT or SEPARATE_ATTRIBS_EXT, 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_EXT and <count> is
    greater than the implement-dependent limit
    MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_EXT.

    The state set by TransformFeedbackVaryingsEXT 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_EXT) or multiple buffer objects (if the buffer mode is
    SEPARATE_ATTRIBS_EXT).  A program will fail to link if:

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

      * any variable name specified in the <varyings> array 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_EXT and the buffer mode is
        SEPARATE_ATTRIBS_EXT; or

      * the total number of components to capture is greater than the constant
        MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT and the buffer mode
        is INTERLEAVED_ATTRIBS_EXT.

    To determine the set of varying variables in a linked program object that
    will be captured in transform feedback mode, use the command:

      void GetTransformFeedbackVaryingEXT(uint program, uint index,
                                          sizei bufSize, sizei *length, 
                                          sizei *size, enum *type, 
                                          char *name);

    This command provides information about the varying variable selected by
    <index>.  An <index> of 0 selects the first varying variable specified in
    the <varyings> array of TransformFeedbackVaryingsEXT, and an <index> of
    TRANSFORM_FEEDBACK_VARYINGS_EXT-1 selects the last such varying variable.
    The value of TRANSFORM_FEEDBACK_VARYINGS_EXT can be queried with
    GetProgramiv (see section 6.1.14).  If <index> is greater than or equal to
    TRANSFORM_FEEDBACK_VARYINGS_EXT, the error INVALID_VALUE is generated.
    The parameter <program> is the name of a program object for which the
    command LinkProgram has been issued in the past.  If a new set of varying
    variables is specified by TransformFeedbackVaryingsEXT after a program
    object has been linked, the information returned by
    GetTransformFeedbackVaryingEXT will not reflect those variables until the
    program is re-linked.

    The name of the selected varying is returned as a null-terminated string
    in <name>. The actual number of characters written into <name>, excluding
    the null terminator, is returned in <length>. If <length> is NULL, no
    length is returned. The maximum number of characters that may be written
    into <name>, including the null terminator, is specified by <bufSize>. The
    returned varying name can be the name of a user defined varying variable
    or the name of a built- in varying (which begin with the prefix "gl_", see
    the OpenGL Shading Language specification for a complete list). The length
    of the longest varying name in program is given by
    TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH_EXT, which can be queried with
    GetProgramiv (see section 6.1.14).

    For the selected varying variable, its type is returned into <type>.  The
    size of the varying is returned into <size>. The value in <size> is in
    units of the type returned in <type>. The type returned can be any of
    FLOAT, FLOAT_VEC2, FLOAT_VEC3, FLOAT_VEC4, INT, INT_VEC2, INT_VEC3,
    INT_VEC4, UNSIGNED_INT, UNSIGNED_INT_VEC2_EXT, UNSIGNED_INT_VEC3_EXT,
    UNSIGNED_INT_VEC4_EXT, FLOAT_MAT2, FLOAT_MAT3, or FLOAT_MAT4.  If an error
    occurred, the return parameters <length>, <size>, <type> and <name> will
    be unmodified.  This command will return as much information about the
    varying variables as possible.  If no information is available, <length>
    will be set to zero and <name> will be an empty string. This situation
    could arise if GetTransformFeedbackVaryingEXT is called after a failed
    link.


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

   (Add new section 3.X, Discarding Rasterization)

    Primitives can be optionally discarded before rasterization by calling
    Enable and Disable with RASTERIZER_DISCARD_EXT. When enabled, primitives
    are discared right before the rasterization stage, but after the optional
    transform feedback stage. When disabled, primitives are passed through to
    the rasterization stage to be processed normally. RASTERIZER_DISCARD_EXT
    applies to the DrawPixels, CopyPixels, Bitmap, Clear and Accum commands as
    well.


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

    (Replace section 4.1.7, "Occlusion Queries", p. 204, with the following)

    Occlusion queries use query objects to track the number of fragments or
    samples that pass the depth test.  An occlusion query can be started and
    finished by calling BeginQuery and EndQuery, respectively, with a <target>
    of SAMPLES_PASSED.

    When an occlusion query starts, the samples-passed count maintained by the
    GL is set to zero.  When an occlusion query is active, the samples-passed
    count is incremented for each fragment that passes the depth test.  If the
    value of SAMPLE BUFFERS is 0, then the samples- passed count is
    incremented by 1 for each fragment. If the value of SAMPLE BUFFERS is 1,
    then the samples-passed count is incremented by the number of samples
    whose coverage bit is set. However, implementations, at their discretion,
    may instead increase the samples-passed count by the value of SAMPLES if
    any sample in the fragment is covered.  When an occlusion query finishes
    and all fragments generated by the commands issued prior to EndQuery have
    been generated, the samples-passed count is written to the corresponding
    query object as the query result value, and the query result for that
    object is marked as available.

    If the samples-passed count overflows, (i.e., exceeds the value 2^n - 1,
    where n is the number of bits in the samples-passed count), its value
    becomes undefined.  It is recommended, but not required, that
    implementations handle this overflow case by saturating at 2^n - 1 and
    incrementing no further.


Additions to Chapter 5 of the OpenGL 2.0 Specification (Special Functions)

    (Add to section 5.4, Display Lists p. 237)

    On p. 241, add the following to the list of vertex buffer object commands
    not compiled into a display list: BindBufferRangeEXT, BindBufferOffsetEXT,
    BindBufferBaseEXT, and TransformFeedbackVaryingsEXT.


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

    Modify the second paragraph of section 6.1.1 (Simple Queries) p244 to read
    as follows:

    ...<data> is a pointer to a scalar or array of the indicated type in which
    to place the returned data. The commands

      void GetIntegerIndexedvEXT(enum param, uint index, int *values);
      void GetBooleanIndexedvEXT(enum param, uint index, boolean *values);

    are used to query indexed state.  <target> is the name of the indexed
    state and <index> is the index of the particular element being queried.
    <data> is a pointer to a scalar or array of the indicated type in which to
    place the returned data. In addition ...

   (Replace Section 6.1.12, Occlusion Queries, p. 254)

    Section 6.1.12, Asynchronous Queries

    The command

      boolean IsQuery(uint id);

    returns TRUE if <id> is the name of a query object. If <id> is zero, or if
    <id> is a non-zero value that is not the name of a query object, IsQuery
    returns FALSE.

    Information about a query target can be queried with the command

      void GetQueryiv(enum target, enum pname, int *params);

    <target> identifies the query target and can be SAMPLES_PASSED for
    occlusion queries or PRIMITIVES_GENERATED_EXT and
    TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_EXT for primitive queries.

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

    If <pname> is QUERY_COUNTER_BITS, 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.

    For primitive queries (PRIMITIVES_GENERATED_EXT and
    TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_EXT) if the number of bits is
    non-zero, the minimum number of bits allowed is 32.

    For occlusion queries (SAMPLES_PASSED), if the number of bits is non-
    zero, the minimum number of bits allowed is a function of the
    implementation's maximum viewport dimensions (MAX_VIEWPORT_DIMS).  The
    counter must be able to represent at least two overdraws for every pixel
    in the viewport. The formula to compute the allowable minimum value (where
    n is the minimum number of bits) is:

      n = min(32, ceil(log_2(maxViewportWidth *
                             maxViewportHeight * 2))).

    The state of a query object can be queried with the commands

      void GetQueryObjectiv(uint id, enum pname, int *params);
      void GetQueryObjectuiv(uint id, enum pname, uint *params);

    If <id> is not the name of a query object, or if the query object named by
    <id> is currently active, then an INVALID_OPERATION error is generated.

    If <pname> is QUERY_RESULT, then the query object's result value is
    returned as a single integer in <params>.  If the value is so large in
    magnitude that it cannot be represented with the requested type, then the
    nearest value representable using the requested type is returned.  If the
    number of query counter bits for any <target> is zero, then the result is
    returned as a single integer with a value of 0.

    There may be an indeterminate delay before the above query returns.  If
    <pname> is QUERY_RESULT_AVAILABLE, FALSE is returned if such a delay would
    be required, TRUE is returned otherwise. It must always be true that if
    any query object returns a result available of TRUE, all queries of the
    same type issued prior to that query must also return TRUE.

    Querying the state for any given query object forces the corresponding
    query to complete within a finite amount of time.

    If multiple queries are issued using the same object name prior to calling
    GetQueryObject[u]iv, the result and availability information returned will
    always be from the last query issued.  The results from any queries before
    the last one will be lost if they are not retrieved before starting a new
    query on the same <target> and <id>.


    (Add to Section 6.1.13, Buffer Objects, p. 255)

    Add the following paragraph to the bottom of this section, p. 256.

    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
    GetIntegerIndexedvEXT() with <param> set to
    TRANSFORM_FEEDBACK_BUFFER_BINDING_EXT.  <index> has to be in the range 0
    to MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_EXT - 1, otherwise the error
    INVALID_VALUE is generated. 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>.

    To query the starting offset or size of the range of each buffer object
    binding used for transform feedback, call GetIntegerIndexedvEXT() with
    <param> set to TRANSFORM_FEEDBACK_BUFFER_START_EXT or
    TRANSFORM_FEEDBACK_BUFFER_SIZE_EXT respectively.  The error INVALID_VALUE
    is generated if <index> not in the range 0 to
    MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_EXT - 1.  If the parameter
    (starting offset or size) was not specified when the buffer object was
    bound, or if no buffer object is bound to <index>, zero is returned.

    (add to Section 6.1.14, Shader and Program Queries, p. 256)

    Add the following paragraph to the bottom of page 257:

    If <pname> is TRANSFORM_FEEDBACK_BUFFER_MODE_EXT, the buffer mode, used
    when transform feedback is active, is returned. It can be one of
    SEPARATE_ATTRIBS_EXT or INTERLEAVED_ATTRIBS_EXT.  If <pname> is
    TRANSFORM_FEEDBACK_VARINGS_EXT, the number of varying variables to capture
    in transform feedback mode for the program is returned.  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, is returned. If no varyings are used for transform feedback,
    zero is returned.

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

    None.

Additions to the AGL/GLX/WGL Specifications

    None.

GLX Protocol

    UNDER DEVELOPMENT

Interactions with NV_transform_feedback

    NV_transform_feedback is the initial version of this extension, which
    includes three capabilities not provided here:

      * support for transform feedback with assembly vertex/geometry programs
        and fixed-function vertex processing;

      * the ability to change the set of GLSL varying variables to capture in
        transform feedback mode without re-linking; and 

      * the "active varying" API that enumerates all varying variables in a
        program object that are considered active.

    This extension provides one capability not provided by
    NV_transform_feedback -- the ability and requirement to specify the set of
    varying variables used for transform feedback prior to linking.

    If both extensions are supported, the following happens:

      * When a program is linked, the active varying state defined in the NV
        extension is updated.  For the purposes of this API, any variables
        enabled for transform feedback via TransformFeedbackVaryingsEXT() are
        considered active.

      * When a program is linked, the transform feedback configuration is
        built from the state provided by TransformFeedbackVaryingsEXT() as in
        the current extension.  In terms of the NV extension, it is as though
        the linker had queried the locations of each varying specified in
        TransformFeedbackVaryingsEXT() and then called the
        TransformFeedbackVaryingsNV() to update the transform feedback
        configuration post-link.  If no varying variables were specified by
        TransformFeedbackVaryingsEXT(), the transform feedback configuration
        is reset to an empty default state after linking, just as is always
        the case when using the NV extension alone.

      * Calling TransformFeedbackVaryingsNV() after linking allows an
        application to update the transform feedback state post-link.  Any
        transform feedback state set when a program is linked is replaced with
        the state specified by TransformFeedbackVaryingsNV().

      * Calling TransformFeedbackVaryingsEXT() after linking continues to have
        no effect.

      * The EXT and NV versions of all functions defined in both extension,
        other than TransformFeedbackVaryings*(), operate identically.

      * BeginTransformFeedbackEXT() does not require the use of a GLSL program
        object if both extensions are supported.  If no GLSL program object is
        active, transform feedback is still enabled and captures the
        attributes specified by TransformFeedbackAttribsNV().


Interactions with EXT_timer_query

    EXT_timer_query is the first extension to generalize the BeginQuery and
    EndQuery mechanism introduced by ARB_occlusion_query and OpenGL 1.5 to
    cover an additional query type.  This extension is the second.  This
    extension is written against the OpenGL 2.0 specification and uses most of
    the modifications in the EXT_timer_query specification.  If
    EXT_timer_query is supported, timer queries need to be added as a third
    query type.


Dependencies on EXT_geometry_shader4

    If EXT_geometry_shader4 is not supported, delete all references to
    geometry shaders.


Errors

    The error INVALID_OPERATION is generated by BeginQuery if called with an
    <id> of zero, if the active query object name for <target> is non- zero,
    or if <id> is the active query object name for any query type.

    The error INVALID_OPERATION is generated by EndQuery if the active query
    object name for <target> is zero.

    The error INVALID_OPERATION is generated if Begin, or any command that
    performs an explicit Begin, is called when:

      * a geometry shader is not active and <mode> does not match the allowed
        begin modes for the current transform feedback state as given by table
        X.1.

      * a geometry shader is active and the output primitive type of the
        geometry shader does not match the allowed begin modes for the current
        transform feedback state as given by table X.1.

    The error INVALID_OPERATION is generated by BeginTransformFeedbackEXT if
    any transform feedback buffer object binding point used in transform
    feedback mode does not have a buffer object bound.

    The error INVALID_OPERATION is also generated by BeginTransformFeedbackEXT
    if no binding points would be used, either because no program object is
    active or because the active program object has specified no varying
    variables to record.

    If transform feedback is active, the error INVALID_OPERATION is generated
    by BeginTransformFeedbackEXT; UseProgram; LinkProgram if called on the
    currently in use program object; and BindBufferRangeEXT,
    BindBufferOffsetEXT, or BindBufferBaseEXT if <target> is
    TRANSFORM_FEEDBACK_BUFFER_EXT.

    If transform feedback is inactive, the error INVALID_OPERATION is
    generated by EndTransformFeedbackEXT.

    The error INVALID_VALUE is generated by BindBufferRangeEXT,
    BindBufferOffsetEXT, or BindBufferBaseEXT if <index> is greater or equal
    than MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_EXT.

    The error INVALID_VALUE is generated by BindBufferRangeEXT if the value of
    <size> is less than or equal to zero, or not word-aligned.

    The error INVALID_VALUE is generated by BindBufferRangeEXT or
    BindBufferOffsetEXT if <offset> is not word-aligned.

    The error INVALID_VALUE is generated by TransformFeedbackVaryingsEXT
    commands if <program> is not the name of a program object, or if
    <bufferMode> is SEPARATE_ATTRIBS_EXT and <count> is greater than
    MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_EXT.

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

    The error INVALID_VALUE is generated by GetIntegerIndexedvEXT() or
    GetBooleanIndexedvEXT() with <param> set to
    TRANSFORM_FEEDBACK_BUFFER_BINDING_EXT if <index> is greater than or equal
    to MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_EXT.


New State

    (Add a new table:  Table 6.X,  Transform Feedback State)

    Get Value             Type    Get Command     Init. Value  Description                Sec    Attrib
    ------------------    ------  --------------  ------------ -------------------------  -----  ------
    TRANSFORM_FEEDBACK_   Z+      GetIntegerv          0        Buffer object bound to    6.1.13   -
      BUFFER_BINDING_EXT                                        generic bind point for
                                                                transform feedback.
    TRANSFORM_FEEDBACK_   nxZ+    GetInteger-          0        Buffer object bound to    6.1.13   -
      BUFFER_BINDING_EXT          IndexedvEXT                   each transform feedback
                                                                attribute stream.
    TRANSFORM_FEEDBACK_   nxZ+    GetInteger-          0        Start offset of binding   6.1.13   -
      BUFFER_START_EXT            IndexedvEXT                   range for each transform
                                                                feedback attrib. stream
    TRANSFORM_FEEDBACK_   nxZ+    GetInteger-          0        Size of binding range     6.1.13   -
      BUFFER_SIZE_EXT             IndexedvEXT                   for each transform
                                                                feedback attrib. stream

   (Modify Table 6.37, p 298, updating the query object state to cover
   transform feedback.)

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

   (Modify Table 6.29, p. 290, Program Object State. Add the following state.)

    Get Value           Type  Get Command   Init. Value  Description                 Sec    Attribute
    ----------------    ----  ------------  -----------  -------------------------   -----  ---------
   TRANSFORM_FEEDBACK_  Z2    GetProgramiv  INTERLEAVED_ Transform feedback mode     6.1.14     -
     BUFFER_MODE_EXT                        ATTRIBS_EXT   for the program
   TRANSFORM_FEEDBACK_  Z+    GetProgramiv       0       Number of varyings to       6.1.14     -
     VARYINGS_EXT                                        stream to buffer object(s)
   TRANSFORM_FEEDBACK_  Z+    GetProgramiv       0       Maximum transform feedback  6.1.14     -
     VARYING_MAX_                                        varying name length
     LENGTH_EXT
        -               Z+    GetTransform-      -       Size of each transform      2.15.3     -
                               Feedback-                 feedback varying variable
                               VaryingEXT
        -               Z+    GetTransform-       -      Type of each transform      2.15.3     -
                               Feedback-                 feedback varying variable
                               VaryingEXT
        -               0+x-  GetTransform-       -      Name of each transform      2.15.3     -
                        char   Feedback-                 feedback varying variable
                               VaryingEXT

   (Add new Table, Query Object State.  Note:  There is nothing transform 
    feedback-specific here; this table should be in the core specification.)

    Get Value           Type  Get Command   Init. Value  Description                 Sec     Attribute
    ----------------    ----  ------------  -----------  -------------------------   ------  ---------
    QUERY_RESULT        Z+    GetQuery-          0       Query object result         6.1.12     -
                               Objectiv                   (query type-dependent)
    QUERY_RESULT_       Z+    GetQuery-        TRUE      Is the query object         6.1.12     -
      AVAILABLE                Objectiv                    result available?


New Implementation Dependent State

   (Modify Table 6.34, p. 295.  Update the query object state to cover
   transform feedback.)

    Get Value               Type Get Command  Minimum Value  Description                  Sec     Attribute
    --------------------    ---- -----------  -------------  --------------------------   ------  ---------
    QUERY_COUNTER_BITS      2xZ+ GetQueryiv   see 6.1.12     Asynchronous query counter   6.1.12    -
                                                             bits (occlusion, timer, 
                                                             tranform feedback queries)

   (Add a new table, Table 6.X. Transform Feedback State.)

   NOTE:  In the "GetValue" columns below, MXFB stands for
   "MAX_TRANSFORM_FEEDBACK".

    Get Value               Type Get Command  Minimum Value  Description                  Sec     Attribute
    --------------------    ---- -----------  -------------  --------------------------   ------  ---------
    MXFB_INTERLEAVED_       Z+   GetIntegerv  64             Max number of components to  2.Y       -
    COMPONENTS_EXT                                           write to a single buffer in
                                                             interleaved mode
    MXFB_SEPARATE_          Z+   GetIntegerv  4              Max number of separate       2.Y       -
    ATTRIBS_EXT                                              attributes or vayings that
                                                             can be captured in transform
                                                             feedback
    MXFB_SEPARATE_          Z+   GetIntegerv  4              Max number of components     2.Y       -
    COMPONENTS_EXT                                           per attribute or varying 
                                                             in separate mode

Issues

    1. How does transform feedback differ from core GL feedback?

      * Transform feedback writes vertex data to buffer objects, which allows
        the data returned to be used directly by vertex pulling.  GL feedback
        mode writes vertex data to a buffer in system memory.

      * Transform feedback is done after transformation, but prior to
        clipping.  The primitives returned contain the original transformed
        vertices produced by vertex or geometry program execution, and does
        not contain any primitives inserted by clipping.

      * Transform feedback supports only a single basic output primitive type
        (points, lines, or triangles), while core GL feedback mode supports
        all primitive types.  Since only one primitive type is supported, the
        data returned does not contain tokens describing each primitive being
        fed back.  Primitive tokens make the data returned by GL feedback mode
        irregular and unsuitable for vertex pulling.

    2. What should this extension be called, and how does it differ from
       previous extensions?

      RESOLVED:  The current name is "EXT_transform_feedback", playing off the
      fact that it is transformed primitives that are handled and the
      similarities to GL feedback mode.  

      This extension is new version of the shipping NV_transform_feedback
      extension with some capabilities removed to ease multi-vendor adoption.
      See the "Interactions with NV_transform_feedback" section for more
      information on the functional differences.

    3. What happens if you bind a buffer for transform feedback that is
       currently bound for other purposes?  Should we somehow detect this case
       and produce an error?

      !!! NBC I feel strongly that we should follow the precedent for
      Map/Unmap. The reason that MapBuffer and UnmapBuffer are a precedent
      here is because while a buffer object is in the mapped state, no GL
      commands are allowed to operate on the buffer object's data.  So by
      analogy, while a buffer is being used for transform feedback, no other
      GL commands should be allowed to operate on the buffer object's data.
      This includes initiating any rendering which would cause the GL to
      source data from an active transform feedback buffer object.

      UNRESOLVED

    4. Should this extension include any new buffer object binding targets, or
       should it overload ARRAY_BUFFER, or should we skip the binding target
       altogether in favor of a buffer object name accepted directly by the
       new GL commands?

      RESOLVED: There are new binding points for XFB along with a new API
      (BindBufferBase etc) to set the internal binding points. A new binding
      point, TRANSFORM_FEEDBACK_BUFFER_EXT is also introduced.

    5. Previous buffer object extensions provided a way to have existing GL
       commands reference a buffer object instead of a user-supplied buffer.
       Should the new commands introduced here allow referencing a
       user-supplied buffer in addition to a buffer object?

      RESOLVED: No. A program can get the contents of the feedback buffer back
      to the CPU using MapBuffer and GetBufferSubData.

    6. Is BeginTransformFeedback really necessary? Could the query just
       initiate the transform feedback mode?

      RESOLUTION: Using BeginTransformFeedback and EndTransformFeedback gives
      a clean place to spec all of the transform-feedback-specific issues
      without cluttering up the query language. Also, the queries don't have
      to be done at the same time as beginning and ending the feedback
      process.

    7. What usage enums should be provided to glBufferData for use in
       conjunction with transform feedback?

      RESOLVED: STREAM_COPY or STREAM_READ are expected to be the most common
      usages. If a buffer object is being written by the GL through transform
      feedback, and the contents of the buffer object are subsequently being
      consumed by the GL (e.g. by being used as a vertex buffer object), then
      this is a *_COPY usage. If the buffer object is being written by the GL
      through transform feedback, but is being consumed by the application
      (e.g. being mapped for read), this is a *_READ usage.  The temporal
      (STREAM, STATIC, or DYNAMIC) component of the usage enum is determined
      by the ratio between how often the contents of the buffer object are
      modified and how often operations that source data from the buffer
      object occur.

    8. What should the behavior be when a buffer object is the active target
       of transform feedback, and it is deleted via DeleteBuffers?

      RESOLVED: Deletion is deferred until the EndTransformFeedback if
      transform feedback is active.

    9. Should we allow more buffers to be bound than are used?

      RESOLVED: Yes. The extra buffers are not in the way and can stay bound.

    10. Should we allow feedback to buffer lists with holes (i.e. 0 and 2
        bound)?

      RESOLVED: No. This makes for an ugly API with the potential for bugs,
      without any real benefit. The application can as well bind all buffers
      needed to incremented indices. It is an invalid operation to not have a
      buffer bound where one is required.

    11. Why only one feedback primitive mode per feedback invocation?

      RESOLVED: Having primitive tokens breaks up the stream and makes it less
      amenable to being read back in as a vertex buffer. Also, mixing multiple
      primitive types makes the counting of primitives less clear for the
      application.

    12. Is RasterPos fed back?

      RESOLVED: No.

    13. Is DrawPixels/CopyPixels/Bitmap fed back?

      RESOLVED: No. Rasterization occurs as normal, but there is no
      output to the feedback buffer. This is consistent with taking a
      tap out of the pipe before clipping.

    14. Why do we need new BindBuffer* functions?

      RESOLVED: All previous buffer object extensions have been retrofits of
      existing pointer-based APIs. New extensions built assuming buffer
      objects don't have that history, so need a new API. The functionality of
      these new functions combines the functionality of BindBuffer, to set the
      external bind point used by calls like MapBuffer and BufferSubData, with
      the functionality to set an internal bind point like VertexAttribPointer
      does.

    15. How do the transform feedback indices, passed to the BindBuffer*
        commands, work with multiple bindings?

      RESOLVED:  The same way that they work with vertex arrays.  There is one
      external bind point, TRANSFORM_FEEDBACK_BUFFER_EXT.  There are n
      internal bind points, selected with the <index> parameter to the
      BindBuffer* commands, where n is some implementation dependent limit.
      The BindBuffer* commands take the buffer passed and bind it to the
      external bind point, as well as to the selected internal bind point.

      For example:

        BindBufferOffsetEXT(TRANSFORM_FEEDBACK_BUFFER_EXT, 0, 1, 12); 
        // XFB index 0 points at buffer 1 with offset 12

        BindBuffer(TRANSFORM_FEEDBACK_BUFFER_EXT, 2); 
        // Buffer 2 is now bound to the external bind point. XFB index 0 still
        // points at buffer 1

        MapBuffer(TRANSFORM_FEEDBACK_BUFFER_EXT, ...); 
        // Maps buffer 2

    16. How are quads/quadstrips/polygons tesselated into triangles?

      RESOLVED: In an implementation-dependent manner. OpenGL doesn't define
      quads or polygons in terms of triangles, so there is no one correct way
      to do it, and different gpus may implement the behavior differently. A
      quad may be split into two triangles in several different ways, and an
      application may not rely on this behavior.

    17. How does this extension interact with display lists?

      RESOLVED: Just like the VBO extension, none of the BindBuffer* commands
      are compiled into a display list.

    18. Does polygon mode state affect the logic that determines if the
        transform feed back primitive mode and the render mode states are
        valid at the start of transform feedback mode?

      RESOLVED: PolygonMode has no influence on the BeginTransFormFeedback
      primitiveMode check since it is performed later in the pipeline.

    19. What to do with incomplete primitives?

      RESOLVED: If there is no room to store one or more vertices of a
      primitive in a buffer object, none of the vertices in that primitive are
      written to the buffer. If a partial primitive enters transform feedback
      (i.e. only two vertices sent in triangles mode), none of the vertices in
      that primitive are written to the buffer object.

    20. Why does TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN_EXT have a
        TRANSFORM_FEEDBACK prefix but PRIMITIVES_GENERATED_EXT doesn't?

      RESOLVED: The number of primitives generated is independent of any
      feedback that is active. The number of primitives that are written is
      only valid for transform feedback - another extension could conceivably
      have a different way of writing out primitives that would require a
      similar but distinct token.

    25. Are primitives sent down the pipeline after transform feedback, or
        discarded?

      RESOLVED: Primitives can be optionally discarded before rasterization by
      calling Enable and Disable with RASTERIZER_DISCARD_EXT. When enabled,
      primitives are discarded after vertex attributes are recorded into the
      buffer objects bound to transform feedback.  When disabled, primitives
      are passed through to the rasterization stage to be clipped and
      rasterized normally. All rasterization operations are discarded, not
      just those that are fed back into the buffer.

      This applies to DrawPixels, CopyPixels, Bitmap, Clear, Accum as well.

    26. If a varying is declared as an array, is the whole array streamed out?

      RESOLVED: No, the application has to specify which elements of an array
      it wants to stream out. Implementations might not be able to stream out
      a large number of components to a single buffer object.  If that is the
      case, the application can stream each element of an array to a different
      buffer object in TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS mode.

    27. Is it possible to capture attributes when using the fixed-function
        pipeline?

      RESOLVED:  Not in this extension, which requires the use of a GLSL
      vertex or geometry shader.  The NV_transform_feedback extension does
      provide this capability.

    28. Should we provide queries to determine the set of varying variables to
        be captured for a program object in transform feedback mode -- i.e.,
        the values in the array of strings <varyings> given to
        TransformFeedbackVaryingsEXT?

      RESOLVED:  Yes; the command GetTransformFeedbackVaryingEXT is provided
      to query the name, size, and type of each varying captured for a linked
      program object in transform feedback mode.  

      Transform feedback-related queries operate only on a linked program
      object.  There is no API available to query transform feedback varying
      state set by TransformFeedbackVaryingsEXT until a program is linked.

    29. What happens if a variable is specified in the array of names passed
        to TransformFeedbackVaryingsEXT, but not needed by the fragment
        shader?  The linker may normally eliminate such variables.

      RESOLVED:  Varying variables specified by TransformFeedbackVaryingsEXT
      are always considered active and count against the total limit on the
      number of active varying components, regardless of the needs of the
      fragment shader.  If such a program object is executed with transform
      feedback active, the values of these variables are computed by the
      vertex or geometry shader and stored in the appropriate buffer object.
      If transform feedback is inactive, the values of such varyings may be
      calculated even though they are only needed for transform feedback.


Revision History

      Rev.    Date    Author    Changes
      ----  --------  --------  ---------------------------------------------
       8    08/09/13  pbrown    Remove extra <varyings> parameter in
                                TransformFeedbackVaryingsEXT.

       7    07/01/13  Jon Leech Change type of TransformFeedbackVaryingsEXT
                                parameter from 'const char **varyings' to
                                'const char * const *varyings' (Bug 10231). 

       6    01/27/11  Jon Leech Change return value for start/size queries
                                when no buffer bound from -1 to zero, to
                                match state tables (Bug 7318).

       5    02/28/08  pbrown    Merged in edits from Apple.  Update status to
                                shipping.  Moved per-object query results into
                                a separate table.

       4    02/20/08  pbrown    Fix incorrect minimum for MAX_TRANSFORM_
                                FEEDBACK_SEPARATE_COMPONENTS_EXT.  Should be
                                4, not 16.

       3    12/13/07  pbrown    Clean up a number of places where "NV" 
                                suffixes were incorrectly carried over from
                                the NV_transform_feedback spec.

       2    08/28/07  pbrown    Document that BeginTransformFeedbackEXT
                                results in an error if no program object is
                                active or if the active program isn't
                                capturing any varyings.

       1    11/30/06  pbrown    Created an initial EXT_transform_feedback 
                                spec by forking off the existing
                                NV_transform_feedback spec.
