Name

    AMD_transform_feedback4

Name Strings

    GL_AMD_transform_feedback4

Contributors

    Graham Sellers, AMD
    Eric Zolnowski, AMD

Contact

    Graham Sellers (graham.sellers 'at' amd.com)

Status

    Shipping

Version

    Last Modified Date:         31/04/2014
    Author Revision:            5

Number

    OpenGL Extension #450

Dependencies

    OpenGL 4.0 or ARB_transform_feedback3 is required.

    This extension is written against the OpenGL Specification, Version 4.4
    (Core Profile).

    This extension is written against the OpenGL Shading Language (GLSL)
    Specification, Version 4.40

Overview

    Transform feedback is a mechanism to record the output of the vertex,
    tessellation evaluation or geometry shader into one or more buffers for
    further processing, recursive rendering or read-back by the client.
    ARB_transform_feedback3 (and OpenGL 4.0) extended the transform feedback
    subsystem to allow multiple streams of primitive information to be
    captured. However, it imposed a limitation that the primitive type for all
    streams must be POINTS if more than one stream is to be captured.
    AMD_transform_feedback3_lines_triangles relaxed that restriction to allow
    lines or triangles to be captured, in the case where multiple streams are
    to be processed. However, it still required that all streams share the same
    primitive type. Additionally, with all current extensions to transform
    feedback, only a single primitive stream may be rasterized.

    This extension enhances transform feedback in two significant ways. First,
    it allows multiple transform feedback streams to be captured, each with its
    own, independent primitve type. Second, it allows any combination of streams
    to be rasterized. As an example, this enables the geometry shader to take
    a single stream of triangle geometry and emit filled triangles with a
    wireframe outline and a point at each vertex, all in a single pass through
    the input vertices. Combined with features such those provided by
    ARB_viewport_array, layered rendering, shader subroutines and so on, an
    application can render several views of its geoemtry, each with a
    radically different style, all in a single pass.

IP Status

    None.

New Procedures and Functions

    None.

New Tokens

    Accepted by the <pname> parameter of Enablei, Disablei and IsEnabledi:

        STREAM_RASTERIZATION_AMD                        0x91A0

Additions to Chapter 11 of the OpenGL 4.4 (Core Profile) Specification
(Programmable Vertex Processing)

    Modify subsection 11.3.4.3, "Geometry Shader Vertex Streams":

    Replace the second to last paragraph of the subsection with:

        The primitives emitted to all vertex streams are passed to the transform
    feedback stage to be captured and written to buffer objects in the manner
    specified by the transform feedback state. The primitives emitted to vertex
    streams for which rasterization is enabled are then passed to subsequent
    pipeline stages for clipping, rasterization, and subsequent fragment
    processing.

    Replace the last paragraph of the subsection with:

        Geometry shaders that emit vertices to multiple vertex streams may
    generate a different primitive type on each stream. Any combination of
    streams may be rasterized (see Section 3.1). This allows a geometry shader
    to transform a single input vertex stream into multiple primitives of
    different types, all of which may be rasterized.

Additions to Chapter 14 of the OpenGL 4.4 (Core Profile) Specification
(Fixed-Function Primitive Assembly and Rasterization)

    Modify Section 14.1 "Discarding Primitives Before Rasterization", p. 409:

        Primitives sent to any vertex stream (see section 13.2) may be processed
    further. When geometry shaders are disabled, all vertices are considered
    to be emitted to stream zero.
        Primitives can be optionally discarded before rasterization but after
    the optional transform feedback stage (see section 13.2). All primitives
    may be discarded by calling Enable with RASTERIZER_DISCARD. When enabled,
    primitives emitted to any stream are discarded. When enabled,
    RASTERIZER_DISCARD also causes the Clear and ClearBuffer* commands to be
    ignored. When RASTERIZER_DISCARD is disabled, primitives emitted on streams
    for which rasterization is enabled are passed through to the rasterization
    stage to be processed normally. Rasterization for specific streams may be
    enabled by calling Enablei (or disabled by calling Disablei) with the
    constant STREAM_RASTERIZATION_AMD and the index of the selected stream.
    Initially, rasterization is enabled for stream zero and is disabled for all
    other streams.
        If primitives are emitted on more than one stream for which
    rasterization is enabled, the order of rasterization of primitives on
    different streams is undefined. However, it is guaranteed that all
    primitives emitted on a single stream are rasterized in the order in which
    they are generated, and that all primitives generated by a single invocation
    of a geometry shader are rasterized in stream order, starting with the
    lowest numbered stream.

Additions to Chapter 15 of the OpenGL 4.4 (Core Profile) Specification
(Programmable Fragment Processing)

    Modify Section 15.2, "Shader Execution"

    Insert the following paragraph to subsection 15.2.2, "Shader Inputs",
    after the paragraph describing gl_SamplePosition on p. 433:

        The built-in read-only variable gl_StreamID contains the index of the
    vertex stream from which the vertices forming the primitive currently being
    rasterized were taken. User defined input varying variables belonging to
    this stream have defined values, whilst all other user defined input
    variables are undefined. When no geometry shader is active, gl_StreamID
    is zero. When a geometry shader is active and writes to multiple output
    vertex streams for which rasterization is enabled, gl_StreamID may range
    from zero to the value of MAX_VERTEX_STREAMS - 1.

Modifications to Chapter 4 of the OpenGL Shading Language Specification,
Version 4.40 (Variables and Types)

    Append to the end of Section 4.4.1 "Input Layout Qualifiers"

        The identifier <stream> is used to specify that a fragment shader input
    variable or block is associated with a particular vertex stream (numbered
    beginning with zero). A default stream number may be declared at global
    scope by qualifying interface qualifier out as in this example:

        layout (stream = 1) in;

        The stream number specified in such a declaration replaces any previous
    default and applies to all subsequent block and variable declarations until
    a new default is established. The initial default stream number is zero.

        Each input block or non-block input variable is associated with a
    vertex stream. If the block or variable is declared with the <stream>
    identifier, it is associated with the specified stream; otherwise, it is
    associated with the current default stream. A block member may be declared
    with a stream identifier, but the specified stream must match the stream
    associated with the containing block. One example:

        layout (stream = 1) in;            // default is now stream 1
        out vec4 var1;                     // var1 belongs to default stream (1)
        layout (stream = 2) in Block1 {    // "Block1" belongs to stream 2
            layout (stream = 2) vec4 var2; // redundant block member stream decl
            layout (stream = 3) vec2 var3; // ILLEGAL (must match block stream)
            vec3 var4;                     // belongs to stream 2
        };
        layout (stream = 0) in;             // default is now stream 0
        in vec4 var5;                       // var5 belongs to default stream (0)
        in Block2 {                         // "Block2" belongs to default stream (0)
            vec4 var6;
        };
        layout ( stream = 3) in vec4 var7;  // var7 belongs to stream 3

        Each fragment processed by the fragment shader receives its input
    variables from a specific stream corresponding to the stream upon which the
    source vertices were emitted in the geometry shader.  Each invocation of
    the fragment shader processes a fragment belonging to a primitive generated
    from vertices emitted to a single stream. The index of the stream to which
    these vertices belong is available in the built-in variable gl_StreamID
    (see Section 7.1, "Built-in Language Variables"). Only those input variables
    belonging to the current stream have defined values. Reading from a variable
    belonging to any other stream may cause undefined behavior, including
    program termination.

Modifications to Chapter 7 of the OpenGL Shading Language Specification,
Version 4.40 (Built-in Variables)

    Add to the list of built-in variables in the fragment language, sec. 7.1,
    p.122.

        in int gl_StreamID;

    Insert the following paragraph after the description of gl_SamplePosition
    on p.122:

    The input variable gl_StreamID indicates the vertex stream from which
    vertices were taken to generate the primitive to which the current fragment
    belongs. This information may be used to deduce which of the fragment
    shader input variables contain defined values. Reading from input variables
    belonging to a vertex stream other than that indicated by gl_StreamID
    may produce undefined behavior, possibly including application termination.

Modifications to Chapter 8 of the OpenGL Shading Language Specification,
Version 4.40 (Built-in Functions)

    Remove the final paragraph of section 8.15 "Geometry Shader Functions" on
    p.180, which disallows shaders with multiple streams that are not all
    set to POINTS primitive type.

Additions to the AGL/GLX/WGL Specifications

    None.

GLX Protocol

    None.

Errors

    INVALID_VALUE is generated by Enablei, Disablei and IsEnabledi if <target>
    is STREAM_RASTERIZATION_AMD and <index> is greater than or equal to
    MAX_VERTEX_STREAMS_AMD.

New State

    Append to table 23.9, Rasterization

    +---------------------------------------------------+-----------+-------------------+---------------+-----------------------------------------------+-------+
    |                                                   |           | Get               | Initial       |                                               |       |
    | Get Value                                         | Type      | Command           | Value         | Description                                   | Sec.  |
    +---------------------------------------------------+-----------+-------------------+---------------+-----------------------------------------------+-------+
    | STREAM_RASTERIZATION_AMD                          | nxB       | GetBoolean        | See 14.1      | Per stream rasterizer enable                  | 14.1  |
    +---------------------------------------------------+-----------+-------------------+---------------+-----------------------------------------------+-------+

Issues

    1) Why is rasterization order undefined?

    DISCUSSION: Implementations typically break large draws into chunks and
    process each separately. Within each chunk, the rasterization order is
    guaranteed. Between chunks, ordering is also guaranteed - everything in
    early chunks is rasterized before later chunks. However, this means
    that primitives emitted to higher numbered streams in early chunks will
    be rasterized before primitives emitted to lower numbered streams in
    later chunks. Because the boundaries between chunks are not necessarily
    in fixed positions, it is not possible to specify where they will be and
    therefore guarantee rasterization order.

    2) Is this still useful then?

    RESOLVED: Yes, sure. If rendering is order independent (depth test on,
    blending off for example), or can be guaranteed to not overlap (viewport
    arrays, layered rendering and so on), it makes no difference whether
    rasterization order between streams is guaranteed or not.

    3) What's the need for multiple 'streams' in the fragment shader?

    DISCUSSION: In unextended OpenGL, the inputs to the fragment shader are
    derived from the vertices generated on stream 0 in the geometry shader
    (the vertex shader always writes to stream 0). When multiple streams can
    be rasterized, the fragment shader can be invoked as part of a primitive
    on any stream. As each stream can have wildly different outputs in the
    geometry shader, it is really not possible to have only a single set
    of inputs in the fragment shader. Therefore, we expose each stream
    independently. Only those variables written by the geometry shader on the
    stream from which the current primitive was generated will be defined,
    and the others will likely have garbage in them (aliases of the real
    variables). That stream is given by the new gl_StreamID built-in in the
    fragment shader. Other built-in variables (such as gl_FragCoord) are
    always available on any stream.

Revision History

    Rev.    Date      Author    Changes
    ----  ----------  --------  -----------------------------------------
    5     31/04/2014  gsellers  Update for OpenGL 4.4, ready for posting.
    4     12/03/2012  gsellers  Update against OpenGL 4.3.
    3     05/01/2011  gsellers  Assign enumerants
    2     10/14/2010  gsellers  Add fragment shader streams.
    1     10/11/2010  gsellers  Initial revision
