Name

    NV_fragment_program4

Name Strings

    (none)

Contact

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

Status

    Shipping for GeForce 8 Series (November 2006)

Version

    Last Modified Date:         05/26/09
    NVIDIA Revision:            6

Number

    335

Dependencies

    OpenGL 1.1 is required.

    NV_gpu_program4 is required.  This extension is supported if
    "GL_NV_gpu_program4" is found in the extension string.

    ATI_draw_buffers and ARB_draw_buffers trivially affects the definition of
    this specification.

    ARB_fragment_program_shadow trivially affects the definition of this
    specification.

    NV_primitive_restart trivially affects the definition of this extension.

    This extension is written against the OpenGL 2.0 specification.

Overview

    This extension builds on the common assembly instruction set
    infrastructure provided by NV_gpu_program4, adding fragment
    program-specific features.

    This extension provides interpolation modifiers to fragment program
    attributes allowing programs to specify that specified attributes be
    flat-shaded (constant over a primitive), centroid-sampled (multisample
    rendering), or interpolated linearly in screen space.  The set of input
    and output bindings provided includes all bindings supported by
    ARB_fragment_program.  Additional input bindings are provided to determine
    whether fragments were generated by front- or back-facing primitives
    ("fragment.facing"), to identify the individual primitive used to generate
    the fragment ("primitive.id"), and to determine distances to user clip
    planes ("fragment.clip[n]").  Additionally generic input attributes allow
    a fragment program to receive a greater number of attributes from previous
    pipeline stages than possible using only the pre-defined fixed-function
    attributes.

    By and large, programs written to ARB_fragment_program can be ported
    directly by simply changing the program header from "!!ARBfp1.0" to
    "!!NVfp4.0", and then modifying instructions to take advantage of the
    expanded feature set.  There are a small number of areas where this
    extension is not a functional superset of previous fragment program
    extensions, which are documented in the NV_gpu_program4 specification.

New Procedures and Functions

    None.

New Tokens

    None.

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

    Modify Section 2.X, GPU Programs

    (insert after second paragraph)

    Fragment Programs

    Fragment programs are used to compute the transformed attributes of a
    fragment, in lieu of the set of fixed-function operations described in
    sections 3.8 through 3.10.  Fragment programs are run on a single fragment
    at a time, and the state of neighboring fragments is not explicitly
    available.  (In practice, fragment programs may be run on a block of
    fragments, and neighboring fragments' attributes may be used for texture
    LOD calculations or partial derivative approximation.)  The inputs
    available to a fragment program are the interpolated attributes of a
    fragment, which include (among other things) window-space position,
    primary and secondary colors, and texture coordinates.  The results of the
    program are one (or more) colors and possibly a new window Z coordinate.
    A fragment program can not modify the (X,Y) location of the fragment.

    Modify Section 2.X.2, Program Grammar

    (replace third paragraph)

    Fragment programs are required to begin with the header string
    "!!NVfp4.0".  This header string identifies the subsequent program body as
    being a fragment program and indicates that it should be parsed according
    to the base NV_gpu_program4 grammar plus the additions below.  Program
    string parsing begins with the character immediately following the header
    string.

    (add the following grammar rules to the NV_gpu_program4 base grammar)

    <instruction>           ::= <SpecialInstruction>

    <varModifier>           ::= <interpModifier>

    <SpecialInstruction>    ::= "KIL" <opModifiers> <killCond>
                              | "DDX" <opModifiers> <instResult> "," 
                                <instOperandV>
                              | "DDY" <opModifiers> <instResult> "," 
                                <instOperandV>

    <killCond>              ::= <instOperandV>

    <interpModifier>        ::= "FLAT"
                              | "CENTROID"
                              | "NOPERSPECTIVE"

    <attribBasic>           ::= <fragPrefix> "fogcoord"
                              | <fragPrefix> "position"
                              | <fragPrefix> "facing"
                              | <attribTexCoord> <optArrayMemAbs>
                              | <attribClip> <arrayMemAbs>
                              | <attribGeneric> <arrayMemAbs>
                              | "primitive" "." "id"

    <attribColor>           ::= <fragPrefix> "color"

    <attribMulti>           ::= <attribTexCoord> <arrayRange>
                              | <attribClip> <arrayRange>
                              | <attribGeneric> <arrayRange>

    <attribTexCoord>        ::= <fragPrefix> "texcoord"

    <attribClip>            ::= <fragPrefix> "clip"

    <attribGeneric>         ::= <fragPrefix> "attrib"

    <fragPrefix>            ::= "fragment" "."

    <resultBasic>           ::= <resPrefix> "color" <resultOptColorNum>
                              | <resPrefix> "depth"

    <resultOptColorNum>     ::= /* empty */

    <resPrefix>             ::= "result" "."

    (add the following subsection to section 2.X.3.1, Program Variable Types)

    Explicitly declared fragment program attribute variables may have one or
    more interpolation modifiers that control how per-fragment values are
    computed.

    An attribute variable declared as "FLAT" will be flat-shaded.  For such
    variables, the value of the attribute will be constant over an entire
    primitive and will taken from the provoking vertex of the primitive, as
    described in Section 2.14.7.  If "FLAT" is not specified, attributes will
    be interpolated as described in Chapter 3, with the exception that
    attribute variables bound to colors will still be flat-shaded if the shade
    model (section 2.14.7) is FLAT.  If an attribute variable declared as
    "FLAT" corresponds to a texture coordinate replaced by a point sprite
    (s,t) value (section 3.3.1), the value of the attribute is undefined.

    An attribute variable declared as "CENTROID" will be interpolated using a
    point on or inside the primitive, if possible, when doing multisample line
    or polygon rasterization (sections 3.4.4 and 3.5.6).  This method can
    avoid artifacts during multisample rasterization when some samples of a
    pixel are covered, but the sample location used is outside the primitive.
    Note that when centroid sampling, the sample points used to generate
    attribute values for adjacent pixels may not be evenly spaced, which can
    lead to artifacts when evaluating partial derivatives or performing
    texture LOD calculations needed for mipmapping.  If "CENTROID" is not
    specified, attributes may be sampled anywhere inside the pixel as
    permitted by the specification, including at points outside the primitive.

    An attribute variable declared as "NOPERSPECTIVE" will be interpolated
    using a method that is linear in screen space, as described in equation
    3.7 and the appoximation that follows equation 3.8.  If "NOPERSPECTIVE" is
    not specified, attributes must be interpolated with perspective
    correction, as described in equations 3.6 and 3.8.  When clipping lines or
    polygons, an alternate method is used to compute the attributes of
    vertices introduced by clipping when they are specified as "NOPERSPECTIVE"
    (section 2.14.8).

    Implicitly declared attribute variables (bindings used directly in a
    program instruction) will inherit the interpolation modifiers of any
    explicitly declared attribute variable using the same binding.  If no such
    variable exists, default interpolation modes will be used.

    For fragments generated by point primitives, DrawPixels, and Bitmap,
    interpolation modifiers have no effect.

    Implementations are not required to support arithmetic interpolation of
    integer values written by a previous pipeline stage.  Integer fragment
    program attribute variables must be flat-shaded; a program will fail to
    load if it declares a variable with the "INT" or "UINT" data type
    modifiers without the "FLAT" interpolation modifier.

    There are several additional limitations on the use of interpolation
    modifiers.  A fragment program will fail to load:

      * if an interpolation modifier is specified when declaring a
        non-attribute variable,

      * if the same interpolation modifier is specified more than once in a
        single declaration (e.g., "CENTROID CENTROID ATTRIB"),

      * if the "FLAT" modifier is used together with either "CENTROID" or
        "NOPERSPECTIVE" in a single declaration,

      * if any interpolation modifier is specified when declaring a variable
        bound to a fragment's position, face direction, fog coordinate, or any
        interpolated clip distance,

      * if multiple attribute variables with different interpolation modifiers
        are bound to the same fragment attribute, or

      * if one variable is bound to the fragment's primary color and a second
        variable with different interpolation modifiers is bound the the
        fragment's secondary color.

    (add the following subsection to section 2.X.3.2, Program Attribute
    Variables)

    Fragment program attribute variables describe the attributes of a fragment
    produced during rasterization.  The set of available bindings is
    enumerated in Table X.X.

    Most attributes correspond to per-vertex attributes that are interpolated
    over a primitive; such attributes are subject to the interpolation
    modifiers described in section 2.X.3.1.  The fragment's position, facing,
    and primitive IDs are the exceptions, and are generated specially during
    rasterization.  Since two-sided color selection occurs prior to
    rasterization, there are no distinct "front" or "back" colors available to
    fragment programs.  A single set of colors is available, which corresponds
    to interpolated front or back vertex colors.

    If geometry programs are enabled, attributes will be obtained by
    interpolating per-vertex outputs written by the geometry program.  If
    geometry programs are disabled, but vertex programs are enabled,
    attributes will be obtained by interpolating per-vertex outputs written by
    the vertex program.  In either case, the fragment program attributes
    should be read using the same component data type used to write the vertex
    output attributes in the geometry or vertex program.  The value of any
    attribute corresponding to a vertex output not written by the geometry or
    vertex program is undefined.

    If neither geometry nor vertex programs are used, attributes will be
    obtained by interpolating per-vertex values computed by fixed-function
    vertex processing.  All interpolated fragment attributes should be read as
    floating-point values.

      Fragment Attribute Binding  Components  Underlying State
      --------------------------  ----------  ----------------------------
        fragment.color            (r,g,b,a)   primary color
        fragment.color.primary    (r,g,b,a)   primary color
        fragment.color.secondary  (r,g,b,a)   secondary color
        fragment.texcoord         (s,t,r,q)   texture coordinate, unit 0
        fragment.texcoord[n]      (s,t,r,q)   texture coordinate, unit n
        fragment.fogcoord         (f,-,-,-)   fog distance/coordinate
      * fragment.clip[n]          (c,-,-,-)   interpolated clip distance n
        fragment.attrib[n]        (x,y,z,w)   generic interpolant n
        fragment.texcoord[n..o]   (s,t,r,q)   texture coordinates n thru o
      * fragment.clip[n..o]       (c,-,-,-)   clip distances n thru o
        fragment.attrib[n..o]     (x,y,z,w)   generic interpolants n thru o
      * fragment.position         (x,y,z,1/w) window position
      * fragment.facing           (f,-,-,-)   fragment facing
      * primitive.id              (id,-,-,-)  primitive number

      Table X.X:  Fragment Attribute Bindings.  The "Components" column
      indicates the mapping of the state in the "Underlying State" column.
      Bindings containing "[n]" require an integer value of <n> to select an
      individual item.  Interpolation modifiers are not supported on variables
      that use bindings labeled with "*".

    If a fragment attribute binding matches "fragment.color" or
    "fragment.color.primary", the "x", "y", "z", and "w" components of the
    fragment attribute variable are filled with the "r", "g", "b", and "a"
    components, respectively, of the fragment's primary color.

    If a fragment attribute binding matches "fragment.color.secondary", the
    "x", "y", "z", and "w" components of the fragment attribute variable are
    filled with the "r", "g", "b", and "a" components, respectively, of the
    fragment's secondary color.

    If a fragment attribute binding matches "fragment.texcoord" or
    "fragment.texcoord[n]", the "x", "y", "z", and "w" components of the
    fragment attribute variable are filled with the "s", "t", "r", and "q"
    components, respectively, of the fragment texture coordinates for texture
    unit <n>.  If "[n]" is omitted, texture unit zero is used.

    If a fragment attribute binding matches "fragment.fogcoord", the "x"
    component of the fragment attribute variable is filled with either the
    fragment eye distance or the fog coordinate, depending on whether the fog
    source is set to FRAGMENT_DEPTH_EXT or FOG_COORDINATE_EXT, respectively.
    The "y", "z", and "w" coordinates are undefined.

    If a fragment attribute binding matches "fragment.clip[n]", the "x"
    component of the fragment attribute variable is filled with the
    interpolated value of clip distance <n>, as written by the vertex or
    geometry program.  The "y", "z", and "w" components of the variable are
    undefined.  If fixed-function vertex processing or position-invariant
    vertex programs are used with geometry programs disabled, clip distances
    are obtained by interpolating the per-clip plane dot product:

      (p_1' p_2' p_3' p_4') dot (x_e y_e z_e w_e),

    for clip plane <n> as described in section 2.12.  The clip distance for
    clip plane <n> is undefined if clip plane <n> is disabled.

    If a fragment attribute binding matches "fragment.attrib[n]", the "x",
    "y", "z", and "w" components of the fragment attribute variable are filled
    with the "x", "y", "z", and "w" components of generic interpolant <n>.
    All generic interpolants will be undefined when used with fixed-function
    vertex processing with no geometry program enabled.

    If a fragment attribute binding matches "fragment.texcoord[n..o]",
    "fragment.clip[n..o]", or "fragment.attrib[n..o]", a sequence of 1+<o>-<n>
    bindings is created.  For texture coordinate bindings, it is as though the
    sequence "fragment.texcoord[n], fragment.texcoord[n+1],
    ... fragment.texcoord[o]" were specfied.  These bindings are available
    only in explicit declarations of array variables.  A program will fail to
    load if <n> is greater than <o>.

    If a fragment attribute binding matches "fragment.position", the "x" and
    "y" components of the fragment attribute variable are filled with the
    floating-point (x,y) window coordinates of the fragment center, relative
    to the lower left corner of the window.  The "z" component is filled with
    the fragment's z window coordinate.  If z window coordinates are
    represented internally by the GL as fixed-point values, the z window
    coordinate undergoes an implied conversion to floating point.  This
    conversion must leave the values 0 and 1 invariant.  The "w" component is
    filled with the reciprocal of the fragment's clip w coordinate.

    If a fragment attribute binding matches "fragment.facing", the "x"
    component of the fragment attribute variable is filled with +1.0 or -1.0,
    depending on the orientation of the primitive producing the fragment.  If
    the fragment is generated by a back-facing polygon (including point- and
    line-mode polygons), the facing is -1.0; otherwise, the facing is +1.0.
    The "y", "z", and "w" coordinates are undefined.

    If a fragment attribute binding matches "primitive.id", the "x" component
    of the fragment attribute variable is filled with a single integer.  If a
    geometry program is active, this value is obtained by taking the primitive
    ID value emitted by the geometry program for the provoking vertex.  If no
    geometry program is active, the value is the number of primitives
    processed by the rasterizer since the last time Begin was called (directly
    or indirectly via vertex array functions).  The first primitive generated
    after a Begin is numbered zero, and the primitive ID counter is
    incremented after every individual point, line, or polygon primitive is
    processed.  For polygons drawn in point or line mode, the primitive ID
    counter is incremented only once, even though multiple points or lines may
    be drawn.  For QUADS and QUAD_STRIP primitives that are decomposed into
    triangles, the primitive ID is incremented after each complete quad is
    processed.  For POLYGON primitives, the primitive ID counter is zero.  The
    primitive ID is zero for fragments generated by DrawPixels or Bitmap.
    Restarting a primitive topology using the primitive restart index has no
    effect on the primitive ID counter.  The "y", "z", and "w" components of
    the variable are always undefined.

    (add the following subsection to section 2.X.3.5, Program Results.)

    Fragment programs produce final fragment values, and the set of result
    variables available to such programs correspond to the final attributes of
    a fragment.  Fragment program result variables may not be declared as
    arrays.

    The set of allowable result variable bindings is given in Table X.X.

      Binding                        Components  Description
      -----------------------------  ----------  ----------------------------
      result.color                   (r,g,b,a)   color
      result.color[n]                (r,g,b,a)   color output n
      result.depth                   (*,*,d,*)   depth coordinate

      Table X.X:  Fragment Result Variable Bindings.
      Components labeled "*" are unused.

    If a result variable binding matches "result.color", updates to the "x",
    "y", "z", and "w" components of the result variable modify the "r", "g",
    "b", and "a" components, respectively, of the fragment's output color.

    If a result variable binding matches "result.color[n]" and the
    ARB_draw_buffers program option is specified, updates to the "x", "y",
    "z", and "w" components of the color result variable modify the "r", "g",
    "b", and "a" components, respectively, of the fragment output color
    numbered <n>.  If the ARB_draw_buffers program option is not specified,
    the "result.color[n]" binding is unavailable.

    If a result variable binding matches "result.depth", updates to the "z"
    component of the result variable modify the fragment's output depth value.
    If the "result.depth" binding is not in used in a variable written to by
    any instruction in the fragment program, the interpolated depth value
    produced by rasterization is used as if fragment program mode is not
    enabled.  Otherwise, the value written by the fragment program is used,
    and the fragment's final depth value is undefined if the program did not
    end up writing a depth value due to flow control or write masks.  Writes
    to any component of depth other than the "z" component have no effect.

    (modify Table X.13 in section 2.X.4, Program Instructions, to include the
    following.)

                Modifiers 
    Instruction F I C S H D  Inputs     Out  Description
    ----------- - - - - - -  ---------- ---  --------------------------------
    DDX         X - X X X F  v          v    partial derivative relative to X
    DDY         X - X X X F  v          v    partial derivative relative to Y
    KIL         X X - - X F  vc         -    kill fragment

    (add the following subsection to section 2.X.6, Program Options.)

    Section 2.X.6.Y, Fragment Program Options

    + Fixed-Function Fog Emulation (ARB_fog_exp, ARB_fog_exp2, ARB_fog_linear)

    If a fragment program specifies one of the options "ARB_fog_exp",
    "ARB_fog_exp2", or "ARB_fog_linear", the program will apply fog to the
    program's final color using a fog mode of EXP, EXP2, or LINEAR,
    respectively, as described in section 3.10.

    When a fog option is specified in a fragment program, semantic
    restrictions are added to indicate that a fragment program will fail to
    load if the number of temporaries it contains exceeds the
    implementation-dependent limit minus 1, if the number of attributes it
    contains exceeds the implementation-dependent limit minus 1, or if the
    number of parameters it contains exceeds the implementation-dependent
    limit minus 2.

    Additionally, when the ARB_fog_exp option is specified in a fragment
    program, a semantic restriction is added to indicate that a fragment
    program will fail to load if the number of instructions or ALU
    instructions it contains exceeds the implementation-dependent limit minus
    3.  When the ARB_fog_exp2 option is specified in a fragment program, a
    semantic restriction is added to indicate that a fragment program will
    fail to load if the number of instructions or ALU instructions it contains
    exceeds the implementation-dependent limit minus 4.  When the
    ARB_fog_linear option is specified in a fragment program, a semantic
    restriction is added to indicate that a fragment program will fail to load
    if the number of instructions or ALU instructions it contains exceeds the
    implementation-dependent limit minus 2.

    Only one fog application option may be specified by any given fragment
    program.  A fragment program that specifies more than one of the program
    options "ARB_fog_exp", "ARB_fog_exp2", and "ARB_fog_linear", will fail to
    load.

    + Precision Hints (ARB_precision_hint_fastest, ARB_precision_hint_nicest)

    Fragment program computations are carried out at an implementation-
    dependent precision.  However, some implementations may be able to perform
    fragment program computations at more than one precision, and may be able
    to trade off computation precision for performance.

    If a fragment program specifies the "ARB_precision_hint_fastest" program
    option, implementations should select precision to minimize program
    execution time, with possibly reduced precision.  If a fragment program
    specifies the "ARB_precision_hint_nicest" program option, implementations
    should maximize the precision, with possibly increased execution time.

    Only one precision control option may be specified by any given fragment
    program.  A fragment program that specifies both the
    "ARB_precision_hint_fastest" and "ARB_precision_hint_nicest" program
    options will fail to load.

    + Multiple Color Outputs (ARB_draw_buffers, ATI_draw_buffers)

    If a fragment program specifies the "ARB_draw_buffers" or
    "ATI_draw_buffers" option, it will generate multiple output colors, and
    the result binding "result.color[n]" is allowed, as described in section
    2.X.3.5.  If this option is not specified, a fragment program that
    attempts to bind "result.color[n]" will fail to load, and only
    "result.color" will be allowed.

    The multiple color outputs will typically be written to an ordered list of
    draw buffers in the manner described in the ARB_draw_buffers extension
    specification.

    + Fragment Program Shadows (ARB_fragment_program_shadow)

    The ARB_fragment_program_shadow option introduced a set of "SHADOW"
    texture targets and made the results of depth texture lookups undefined
    unless the texture format and compare mode were consistent with the target
    provided in the fragment program instruction.  This behavior is enabled by
    default in NV_gpu_program4; specifying the option is not illegal but has
    no additional effect.

    (add the following subsection to section 2.X.7, Program Declarations.)

    Section 2.X.7.Y, Fragment Program Declarations

    No declarations are supported at present for fragment programs.


    (add the following subsection to section 2.X.8, Program Instruction Set.)

    Section 2.X.8.Z, DDX:  Partial Derivative Relative to X

    The DDX instruction computes approximate partial derivatives of the four
    components of the single floating-point vector operand with respect to the
    X window coordinate to yield a result vector.  The partial derivatives are
    evaluated at the sample location of the pixel.

      f = VectorLoad(op0);
      result = ComputePartialX(f);

    Note that the partial derivates obtained by this instruction are
    approximate, and derivative-of-derivate instruction sequences may not
    yield accurate second derivatives.  Note also that the sample locations
    for attributes declared with the CENTROID interpolation modifier may not
    be evenly spaced, which can lead to artifacts in derivative calculations.

    DDX supports only floating-point data type modifiers and is available only
    to fragment programs.

    Section 2.X.8.Z, DDY:  Partial Derivative Relative to Y

    The DDY instruction computes approximate partial derivatives of the four
    components of the single operand with respect to the Y window coordinate
    to yield a result vector.  The partial derivatives are evaluated at the
    center of the pixel.

      f = VectorLoad(op0);
      result = ComputePartialY(f);

    Note that the partial derivates obtained by this instruction are
    approximate, and derivative-of-derivate instruction sequences may not
    yield accurate second derivatives.  Note also that the sample locations
    for attributes declared with the CENTROID interpolation modifier may not
    be evenly spaced, which can lead to artifacts in derivative calculations.

    DDY supports only floating-point data type modifiers and is available only
    to fragment programs.

    Section 2.X.8.Z, KIL:  Kill Fragment

    The KIL instruction evaluates a condition and kills a fragment if the test
    passes.  A fragment killed by the KIL instruction is discarded, and will
    not be seen by subsequent stages of the pipeline.

    A KIL instruction may be specified using either a floating-point or
    integer vector operand or a condition code test.

    If a floating-point or integer vector is provided, the fragment is
    discarded if any of its components are negative:

      tmp = VectorLoad(op0);
      if ((tmp.x < 0) || (tmp.y < 0) || 
          (tmp.z < 0) || (tmp.w < 0))
      {
          exit;
      }

    Unsigned integer vector operands are permitted; however, KIL.U will have
    no effect as no component is negative by definition.

    If a condition code test is provided, the fragment is discarded if any
    component of the test passes:

      if (TestCC(rc.c***) || TestCC(rc.*c**) || 
          TestCC(rc.**c*) || TestCC(rc.***c)) 
      {
         exit;
      }

    KIL supports all three data type modifiers.

    KIL is available only to fragment programs.

    Replace Section 2.14.8, and rename it to "Vertex Attribute Clipping"
    (p. 70).
 
    After lighting, clamping or masking and possible flatshading, vertex
    attributes, including colors, texture and fog coordinates, shader varying
    variables, and point sizes computed on a per vertex basis, are clipped.
    Those attributes associated with a vertex that lies within the clip volume
    are unaffected by clipping.  If a primitive is clipped, however, the
    attributes assigned to vertices produced by clipping are produced by
    interpolating attributes along the clipped edge.

    Let the attributes assigned to the two vertices P_1 and P_2 of an
    unclipped edge be a_1 and a_2.  The value of t (section 2.12) for a
    clipped point P is used to obtain the attribute associated with P as

      a = t * a_1 + (1-t) * a_2

    unless the attribute is specified to be interpolated without perspective
    correction in a fragment program.  In that case, the attribute associated
    with P is

      a = t' * a_1 + (1-t') * a_2

    where

      t' = (t * w_1) / (t * w_1 + (1-t) * w_2)

    and w_1 and w_2 are the w clip coordinates of P_1 and P_2,
    respectively. If w_1 or w_2 is either zero or negative, the value of the
    associated attribute is undefined.

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

    None

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

    None

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

    None

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

    None

Additions to the AGL/GLX/WGL Specifications

    None

Dependencies on ARB_draw_buffers and ATI_draw_buffers

    If neither ARB_draw_buffers nor ATI_draw_buffers is supported, then the
    discussion of the ARB_draw_buffers option in section 2.X.6.Y should be
    removed, as well as the result bindings of the form "result.color[n]" and
    "result.color[n..o]".

Dependencies on ARB_fragment_program_shadow

    If ARB_fragment_program_shadow is not supported, then the discussion of
    the ARB_fragment_program_shadow option in section 2.X.6.Y should be
    removed.

Dependencies on NV_primitive_restart

    The spec describes the behavior that primitive restart does not affect the
    primitive ID counter, including for POLYGON primitives (where one could
    argue that the restart index starts a new primitive without a new Begin to
    reset the count.  If NV_primitive_restart is not supported, references to
    that extension in the discussion of the "primitive.id" attribute should be
    removed.

Errors

    None

New State

    None

New Implementation Dependent State

    None

Issues

    (1) How should special interpolation controls be specified?

      RESOLVED:  As a special modifier to fragment program attribute variable
      declarations.  It was decided that the fragment program was the most
      natural place to put the control.  This wouldn't require making a large
      number of related state changes controlling interpolation whenever the
      fragment program used.  The final mechanism using special interpolation
      modifiers was chosen because it fit well with the other variable
      modifiers (for data storage size and data type) provided by
      NV_gpu_program4.  Examples:

            FLAT ATTRIB texcoords[4] = { fragment.texcoord[0..3] };
            CENTROID ATTRIB texcoord4 = fragment.texcoord[4];
            CENTROID NOPERSPECTIVE ATTRIB
              attribs[3] = { fragment.attrib[0..2] };

      There were a variety of options considered, including:

        * special declarations in vertex or geometry programs to specify the
          interpolation type,

        * special declarations in the fragment program to specify one or more
          interpolation type modifiers per binding, such as:

            INTERPOLATE fragment.texcoord[0..3], FLAT;
            INTERPOLATE fragment.texcoord[4], CENTROID;
            INTERPOLATE fragment.attrib[0..2], CENTROID, NOPERSPECTIVE;

        * fixed-function state specifying the interpolation mode

            glInterpolateAttribNV(GL_TEXTURE0, GL_FLAT);
            glInterpolateAttribNV(GL_GENERIC_ATTRIB0, GL_CENTROID_NV);

      Recent updates to GLSL provide similar functionality (for centroid) with
      a similar approach, using a modifier on varying variable declarations.

    (2) How should perspective-incorrect interpolation (linear in screen
        space) and clipping interact?

      RESOLVED:  Primitives with attributes specified to be
      perspective-incorrect should be clipped so that the vertices introduced
      by clipping should have attribute values consistent with the
      interpolation mode.  We do not want to have large color shifts
      introduced by clipping a perspective-incorrect attribute.  For example,
      a primitive that approaches, but doesn't cross, a frustum clip plane
      should look pretty much identical to a similar primitive that just
      barely crosses the clip plane.

      Clipping perspective-incorrect interpolants that cross the W==0 plane is
      very challenging.  The attribute clipping equation provided in the spec
      effectively projects all the original vertices to screen space while
      ignoring the X and Y frustum clip plane.  As W approaches zero, the
      projected X/Y window coordinates become extremely large.  When clipping
      an edge with one vertex inside the frustum and the other out near
      infinity (after projection, due to W approaching zero), the interpolated
      attribute for the entire visible portion of the edge should almost
      exactly match the attribute value of the visible vertex.

      If an outlying vertex approaches and then goes past W==0, it can be said
      to go "to infinity and beyond" in screen space.  The correct answer for
      screen-linear interpolation is no longer obvious, at least to the author
      of this specification.  Rather than trying to figure out what the
      "right" answer is or if one even exists, the results of clipping such
      edges is specified as undefined.

    (3) If a shader wants to use interpolation modifiers without using
        declared variables, is that possible?

      RESOLVED:  Yes.  If "dummy" variables are declared, all interpolants
      bound to that variable will get the variable's interpolation modifiers.
      In the following program:

        FLAT ATTRIB tc02[3] = { fragment.texcoord[0..2] };
        MOV R0, fragment.texcoord[1];
        MOV R1, fragment.texcoord[3];

      The variable R0 will get texture coordinate set 1, which will be
      flat-shaded due to the declaration of "tc02".  The variable R1 will get
      texture coordinate set 3, which will be smooth shaded (default).

    (4) Is it possible to read the same attribute with different interpolation
        modifiers?

      RESOLVED:  No.  A program that tries to do that will fail to compile.

    (5) Why can't fragment program results be declared as arrays?

      RESOLVED:  This is a limitation of the programming model.  If an
      implementation needs to do run-time indexing of fragment program result
      variables (effectively writing to "result.color[A0.x]"), code such as
      the following can be used:

        TEMP colors[4];
        ...
        MOV colors[A0.x], R1;
        MOV colors[3], 12.3;
        ...
        # end of the program
        MOV result.color[0], colors[0];
        MOV result.color[1], colors[1];
        MOV result.color[2], colors[2];
        MOV result.color[3], colors[3];

    (6) Do clip distances require that the corresponding clip planes be
    enabled to be read by a fragment program?

      RESOLVED:  No.

    (7) How do primitive IDs work with fragment programs?

      RESOLVED:  If a geometry program is enabled, the primitive ID is
      consumed by the geometry program and is not automatically available to
      the fragment program.  If the fragment program needs a primitive ID in
      this case, the geometry program can write out a primitive ID using the
      "result.primid" binding, and the fragment program will see the primitive
      ID written for the provoking vertex.

      If no geometry program is enabled, the primitive ID is automatically
      available, and specifies the number of primitives (points, lines, or
      triangles) processed by since the last explicit or implicit Begin call.

    (8) What is the primitive ID for non-geometry commands that generate
    fragments, such as DrawPixels, Bitmap, and CopyPixels.

      RESOLVED:  Zero.

    (9) How does the FLAT interpolation modifier interact with point sprite
    coordinate replacement?

      RESOLVED:  The value of such attributes are undefined.  Specifying these
      two operations together is self-contradictory -- FLAT asks for an
      interpolant that is constant over a primitive, and point sprite
      coordinate interpolation asks for an interpolant that is non-constant
      over a point sprite.


Revision History

    Rev.    Date    Author    Changes
    ----  --------  --------  --------------------------------------------
     6    05/26/09  pbrown    Fix documentation of KIL to support integer
                              operands, as indicated in the opcodes table
                              in NV_gpu_program4.

     5    03/11/09  pbrown    Fix section numbers for option/declaration
                              sections.

     4    11/06/07  pbrown    Documented interaction between the FLAT 
                              interpolation modifier and point sprite
                              coordinate replacement.

    1-3             pbrown    Internal spec development.
