Cg 1.2 RUNTIME API ADDITIONS
    Version 1.2 of the Cg runtime adds a number of new capabilities to the
    existing set of functionality from previous releases. These new features
    include functionality that make it possible to write programs that can
    run more efficiently on the GPU, techniques that help hide some of the
    inherent limitations of some Cg profiles on the GPU, and entrypoints
    that support new language functionality in the Cg 1.2 release.

  Parameter Literalization

    The 1.2 Cg runtime makes it possible to denote some of the parameters to
    a program as having a fixed constant value. This feature can lead to
    substantially more efficient programs in a number of cases. For example,
    a program might have a block of code that implements functionality that
    is only used some of the time:

    float4 main(uniform float enableDazzle, ...) : COLOR { if (enableDazzle)
    { // do lengthy computation } else { // do basic computation } }

    Some hardware profiles don't directly support branching (this includes
    all of the fragment program profiles supported in this release), and
    have to handle code like the program by effectively following both sides
    of the if() test. (They still compute the correct result in the end,
    just not very efficiently.)

    However, if the "enableDazzle" parameter is marked as a literal
    parameter and a value is provided for it, the compiler can generate an
    optimized version of the program with the knowledge of "enableDazzle"'s
    value, just generating GPU code for one of the two cases. This can lead
    to substantial performance improvments. This feature also makes it
    easier to write general purpose shaders with a wide variety of supported
    functionality, while only paying the runtime cost for the functionality
    provided.

    This feature is also useful for parameters with numeric values. For
    example, consider a shader that implements a diffuse reflection model:

    float4 main(uniform float3 lightPos, uniform float3 lightColor, uniform
    float3 Kd, float3 pos : TEXCOORD0, float3 normal : TEXCOORD1) : COLOR {
    return Kd * lightColor * max(0., dot(normalize(lightPos - pos),
    normal)); }

    If the "lightColor" and "Kd" parameters are set to literals, it is
    possible for the compiler to compute the product "Kd * lightColor" once,
    rather than once each time the program executes.

    Given a parameter handle, the cgSetParameterVariability() entrypoint
    sets the variability of a parameter:

      void cgSetParameterVariability(CGparameter param, CGenum vary);

    To set it to a literal parameter, the CG_LITERAL enumerant should be
    passed as the second parameter.

    After a parameter has set to be a literal, the following routines should
    be used to set the parameter's value.

    void cgSetParameter1f(CGparameter param, float x); void
    cgSetParameter2f(CGparameter param, float x, float y); void
    cgSetParameter3f(CGparameter param, float x, float y, float z); void
    cgSetParameter4f(CGparameter param, float x, float y, float z, float w);
    void cgSetParameter1d(CGparameter param, double x); void
    cgSetParameter2d(CGparameter param, double x, double y); void
    cgSetParameter3d(CGparameter param, double x, double y, double z); void
    cgSetParameter4d(CGparameter param, double x, double y, double z, double
    w);

    void cgSetParameter1fv(CGparameter param, const float *v); void
    cgSetParameter2fv(CGparameter param, const float *v); void
    cgSetParameter3fv(CGparameter param, const float *v); void
    cgSetParameter4fv(CGparameter param, const float *v); void
    cgSetParameter1dv(CGparameter param, const double *v); void
    cgSetParameter2dv(CGparameter param, const double *v); void
    cgSetParameter3dv(CGparameter param, const double *v); void
    cgSetParameter4dv(CGparameter param, const double *v);

    void cgSetMatrixParameterdr(CGparameter param, const double *matrix);
    void cgSetMatrixParameterfr(CGparameter param, const float *matrix);
    void cgSetMatrixParameterdc(CGparameter param, const double *matrix);
    void cgSetMatrixParameterfc(CGparameter param, const float *matrix);

    After a parameter has been set to be a literal, or after the value of a
    literal parameter has been changed, the program must be compiled and
    loaded into the GPU, regardless of whether it had already been compiled.
    This issue is discussed further in the section on program recompilation
    below.

  Array Size Specification

    The Cg 1.2 language also adds support for ``unsized array'' variables;
    programs can be written to take parameters that are arrays with an
    indeterminate size. The actual size of these arrays is then set via the
    Cg runtime. This feature is useful for writing general-purpose shaders
    with a minimal performance penalty.

    For example, consider a shader that computes shading given some number
    of light sources. If the information about each light source is stored
    in a struct LightInfo, the shader might be written as:

    float4 main(LightInfo lights[], ...) : COLOR { float4 color =
    float4(0,0,0,1); for (i = 0; i < lights.length; ++i) { // add
    lights[i]'s contribution to color } return color; }

    The runtime can then be used to set the length of the lights[] array
    (and then to initialize the values of the LightInfo structures.) As with
    literal parameters, the program must be recompiled and reloaded after a
    parameter's array size is set or changes.

    These two entrypoints set the size of an unsized array parameter
    referenced by the given parameter handle. To set the size of a
    multidimensional unsized array, all of the dimensions' sizes must be set
    simultaneously, by providing them all via the pointer to an array of
    integer values.

    void cgSetArraySize(CGparameter param, int size); void
    cgSetMultiDimArraySize(CGparameter param, const int *sizes);

    XXX what happens if these are called with an already-sized array?? XXX

    To get the size of an array parameter, the cgGetArraySize() entrypoint
    can be used.

    int cgGetArraySize(CGparameter param, int dimension);

  Program Recompilation at Runtime

    The Cg 1.2 runtime environment will allow automatic and manual
    recompilation of programs. This functionality is useful for multiple
    reasons :

    * Changing variability of parameters
        Parameters may be changed from uniform variability to literal
        variability as described above.

    * Changing value of literal parameters
        Changing the value of a literal parameter will require recompilation
        since the value is used at compile time.

    * Resizing parameter arrays
        Changing the length of a parameter array may require recompilation
        depending on the capabilities of the profile of the program.

    * Binding sub-shader parameters
        Sub-shader parameters are structures that overload methods that need
        to be provided at compile time; they are described below. Binding
        such parameters to program parameters will require recompilation.
        See the Sub-Shaders entry elsewhere in this document for more
        information.

    Recompilation can be executed manually by the application using the
    runtime or automatically by the runtime.

    The entry point:

    void cgCompileProgram(CGprogram program);

    causes the given program to be recompiled, and the function:

    CGbool cgIsProgramCompiled(CGprogram program);

    reurns a boolean value indicating whether the current program needs
    recompilation.

    By default, programs are automatically compiled when cgCreateProgram()
    or cgCreateProgramFromFile() is called. This behavior can be controled
    with the entry point :

        void cgSetAutoCompile(CGcontext ctx, CGenum flag);

    Where flag is one of the following three enumerants :

    * CG_COMPILE_MANUAL
        With this method the application is responsible for manually
        recompiling a program. It may check to see if a program requires
        recompilation with the entry point cgIsProgramCompiled().
        cgCompileProgram() can then be used to force compilation.

    * CG_COMPILE_IMMEDIATE
        CG_COMPILE_IMMEDIATE will force recompilation automatically and
        immediately when a program enters an uncompiled state.

    * CG_COMPILE_LAZY
        This method is similar to CG_COMPILE_IMMEDIATE but will delay
        program recompilation until the program object code is needed. The
        advantage of this method is the reduction of extraneous
        recompilations. The disadvantage is that compile time errors will
        not be encountered when the program is enters the uncompiled state
        but will instead be encountered at some later time.

    For programs that use features like unsized arrays that can not be
    compiled until their array sizes are set, it is good practice to change
    the default behavior of compilation to CG_COMPILE_MANUAL so that
    cgCreateProgram() or cgCreateProgramFromFile() do not unnecessarily
    encounter and report compilation errors.

  Shared Parameters (context global parameters)

    Version 1.2 of the runtime introduces parameters that may be shared
    across programs in the same context via a new binding mechanism. Once
    shared parameters are constructed and bound to program parameters,
    setting the value of the shared parameter will automatically set the
    value of all of the program parameters they are bound to.

     Shared parameters belong to a CGcontext instead of a CGprogram. They
    may be created with the following new entry points :

    CGparameter cgCreateParameter(CGcontext ctx, CGtype type); CGparameter
    cgCreateParameterArray(CGcontext ctx, CGtype type, int length);
    CGparameter cgCreateParameterMultiDimArray(CGcontext ctx, CGtype type,
    int dim, const int *lengths);

    They may be deleted with :

    void cgDestroyParameter(CGparameter param);

    After a parameter has been created, its value should be set with the
    cgSetParameter*() routines described in the literalization section
    above.

     Once a shared parameter is created it may be associated with any number
    of program parameters with the call:

    void cgConnectParameter(CGparameter from, CGparameter to);

    where ``from'' is a parameter created with one of the
    cgCreateParameter() calls, and ``to'' is a program parameter.

    Given a program parameter, the handle to the shared parameter that is
    bound to it (if any) can be found with the call:

    CGparameter cgGetConnectedParameter(CGparameter param);

    It returns NULL if no shared parameter has been connected to ``param''.

    There are also calls that make it possible to find the set of program
    parameters to which a given shared parameter has been connected to. The
    entry point:

    int cgGetNumConnectedToParameters(CGparameter param);

    returns the total number of program parameters that ``param'' has been
    conencted to, and the entry point:

    CGparameter cgGetConnectedToParameter(CGparameter param, int index);

    can be used to get CGparameter handles for each of the program
    parameters to which a shared parameter is connected.

    A shared parameter can be unbound from a program parameter with :

    void cgDisconnectParameter(CGparameter param);

    The context in which a shared parameter was created can be returned
    with:

    CGcontext cgGetParameterContext(CGparameter param);

    And the entrypoint:

    CGbool cgIsParameterGlobal(CGparameter param);

    can be used to determine if a parameter is a shared (global) parameter.

  Shader Interface Support

    From the runtime's perspective, shader interfaces are simply struct
    parameters that have a CGtype associated with them. For example, if the
    following Cg code is included in some program source compiled in the
    runtime :

        interface FooInterface
         {
          float SomeMethod(float x);
         }

        struct FooStruct : FooInterface
         {
          float SomeMethod(float x);
           {
            return(Scale * x);
           }

          float Scale;
         };
   
    The named types FooInterface and FooStruct will be added to the context.
    Each one will have a unique CGtype associated with it. The CGtype can be
    retrieved with :

    CGtype cgGetNamedUserType(CGprogram program, const char *name); int
    cgGetNumUserTypes(CGprogram program); CGtype cgGetUserType(CGprogram
    program, int index);

    CGbool cgIsParentType(CGtype parent, CGtype child); CGbool
    cgIsInterfaceType(CGtype type);

    Once the CGtype has been retrieved, it may be used to construct an
    instance of the struct using cgCreateParameter(). It may then be bound
    to a program parameter of the parent type (in the above example this
    would be FooInterface) using cgBindParameter().

    Calling cgGetParameterType() on such a parameter will return the
    CG_STRUCT to keep backwards compatibility with code that recurses
    parameter trees. In order to obtain the enumerant of the named type the
    following entry point should be used :

    CGtype cgGetParameterNamedType(CGparameter param);

    The parent types of a given named type may be obtained with the
    following entry points :

    int cgGetNumParentTypes(CGtype type); CGtype cgGetParentType(CGtype
    type, int index);

    If Cg source modules with differing definitions of named types are added
    to the same context, an error will be thrown. XXX update for new
    scoping/context/program local definitions stuff XXX

  Updated Parameter Management Routines

    XXX wheer should these go?

    Some entrypoints from before have been updated in backwards compatible
    ways

    CGparameter cgGetFirstParameter(CGprogram prog, CGenum name_space);
    CGparameter cgGetFirstLeafParameter(CGprogram prog, CGenum name_space);

    like cgGetNamedParameter, but limits search to the given name_space
    (CG_PROGRAM or CG_GLOBAL)...

    CGparameter cgGetNamedProgramParameter(CGprogram prog, CGenum
    name_space, const char *name);

