Name

    EXT_separate_shader_objects

Name Strings

    GL_EXT_separate_shader_objects

Contact

    Mark Kilgard, NVIDIA (mjk 'at' nvidia.com)

Contributors

    Pat Brown
    Eric Werness
    Robert Ohannessian
    Jason Green, TransGaming
    Kevin Rogovin 
    Greg Roth

Status

    Shipping in NVIDIA 190.00 release drivers

    NOTE: there is an unrelated OpenGL ES extension also named
    "GL_EXT_separate_shader_objects", found in the OpenGL ES extension
    registry at http://www.khronos.org/registry/gles/ . These two extensions
    have similar purposes, but completely different interfaces.

Version

    Last Modified Date:  March 7, 2013
    Version:             11

Number

    377

Dependencies

    Written based on the wording of the OpenGL 3.0 (August 11, 2008)
    specification.

    This extension requires OpenGL 2.0 or ARB_shader_objects.

    This extension depends on ARB_geometry_shader4, EXT_geometry_shader4,
    and/or NV_geometry_shader4.

Overview

    Prior to this extension, GLSL requires multiple shader domains
    (vertex, fragment, geometry) to be linked into a single monolithic
    program object to specify a GLSL shader for each domain.

    While GLSL's monolithic approach has some advantages for
    optimizing shaders as a unit that span multiple domains, all
    existing GPU hardware supports the more flexible mix-and-match
    approach.

    HLSL9, Cg, the prior OpenGL assembly program extensions, and game
    console programmers favor a more flexible "mix-and-match" approach to
    specifying shaders independently for these different shader domains.
    Many developers build their shader content around the mix-and-match
    approach where they can use a single vertex shader with multiple
    fragment shaders (or vice versa).

    This keep-it-simple extension adapts the "mix-and-match" shader
    domain model for GLSL so different GLSL program objects can be bound
    to different shader domains.

    This extension redefines the operation of glUseProgram(GLenum program)
    to be equivalent to:

        glUseShaderProgramEXT(GL_VERTEX_SHADER, program);
        glUseShaderProgramEXT(GL_GEOMETRY_SHADER_EXT, program);
        glUseShaderProgramEXT(GL_FRAGMENT_SHADER, program);
        glActiveProgramEXT(program);

    You can also call these commands separately to bind each respective
    domain.  The GL_VERTEX_SHADER, GL_GEOMETRY_SHADER_EXT, and
    GL_FRAGMENT_SHADER tokens refer to the conventional vertex, geometry,
    and fragment domains respectively.  glActiveProgramEXT specifies
    the program that glUniform* commands will update.

    Separate linking creates the possibility that certain output varyings
    of a shader may go unread by the subsequent shader inputting varyings.
    In this case, the output varyings are simply ignored.  It is also
    possible input varyings from a shader may not be written as output
    varyings of a preceding shader.  In this case, the unwritten input
    varying values are undefined.  Implementations are encouraged to
    zero these undefined input varying values.

    This extension is a proof-of-concept that separate shader objects
    can work for GLSL and a response to repeated requests for this
    functionality.  There are various loose ends, particularly when
    dealing with user-defined varyings.  The hope is a future extension
    will improve this situation.

New Procedures and Functions

    void UseShaderProgramEXT(enum type, uint program);

    void ActiveProgramEXT(uint program);

    uint CreateShaderProgramEXT(enum type, const char *string);

New Tokens

    Accepted by <type> parameter to GetIntegerv and GetFloatv:

        ACTIVE_PROGRAM_EXT                     0x8B8D (alias for CURRENT_PROGRAM)

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

 -- Section 2.20.2 "Program Objects" (page 91) 

    Add this paragraph after the 6th paragraph:

    "The command

        uint CreateShaderProgramEXT(enum type, const char *sting);

    creates a stand-alone program from a source code string for a single
    shader type.  This command is equivalent to the following command
    sequence:

        const uint shader = CreateShader(type);
        if (shader) {
            const int len = (int) strlen(string);
            ShaderSource(shader, 1, &string, &len);
            CompileShader(shader);
            const uint program = CreateProgram();
            if (program) {
                int compiled = FALSE;
                GetShaderiv(shader, COMPILE_STATUS, &compiled);
                if (compiled) {
                    AttachShader(program, shader);
                    LinkProgram(program);
                    DetachShader(program, shader);
                }

                // Possibly...
                if (active-user-defined-varyings-in-linked-program) {
                    append-error-to-info-log
                    set-program-link-status-false
                }

                append-shader-info-log-to-program-info-log
            }
            DeleteShader(shader);
            return program;
        } else {
            return 0;
        }

    Notice the program may not actually link if the linked program would
    contain active user-defined varyings (because such varyings would
    not be well-defined for a single shader domain).  If this situation
    arises, the info log may explain this.

    Because no shader is returned by CreateShaderProgramEXT and the shader
    that is created is deleted in the course of the command sequence,
    the info log of the shader object is copied to the program so the
    shader's failed info log for the failed compilation is accessible
    to the application."

    Replace the 7th paragraph with:

    "If a valid executable is created, it can be made part of the current
    rendering state with the command:

           void UseShaderProgramEXT(enum type, uint program);

    where type is one of VERTEX_SHADER, GEOMETRY_SHADER_ARB, or
    FRAGMENT_SHADER program shader types, and program is the program
    object program containing valid executable code, i.e. has been linked
    successfully.  Based on the type, the program becomes the current
    vertex, fragment, or geometry shader program respectively and the
    command installs the executable code as part of the respective current
    rendering state.  If UseShaderProgramEXT is called with program set
    to zero, it is as if the GL has no respective (vertex, geometry,
    or fragment) programmable stage configured and the corresponding
    fixed-function path will be used instead.  If program has not been
    successfully linked, the error INVALID_OPERATION is generated and
    the respective current shader state is not modified.

    The command

        void ActiveProgramEXT(uint program);

    sets the linked program named by program to be the active program
    (discussed later in the "Uniform Variables" subsection of section
    2.20.3).  If program has not been successfully linked, the error
    INVALID_OPERATION is generated and active program is not modified.

    The command

        void UseProgram(uint program);

    is equivalent (modulo errors) to calling

        UseShaderProgramEXT(VERTEX_SHADER, program);
        UseShaderProgramEXT(GEOMETRY_SHADER_EXT, program);
        UseShaderProgramEXT(FRAGMENT_SHADER, program);
        ActiveProgramEXT(program);

    If a program object contains multiple shader types but is not bound
    for all its supported shader types, the program object's shader
    types not bound do not affect GL's current rendering operation."

 -- Section 2.15.3 "Shader Variables" (page 97) 

    Replace the 15th paragraph of the "Uniform Variables" section:

    "To load values into the uniform variables of the active program
    object (specified by ActiveProgramEXT), use the commands ..."

    Change the last bullet in the "Uniform Variables" section to:

    "* if there is no active program in use."

 -- Section 2.20.4 "Shader Execution" (page 103) 

    Change the first paragraph to read:

    "If a successfully linked program object that contains a vertex
    shader is made current by calling UseShaderProgramEXT with a type of
    VERTEX_SHADER, the executable version of the vertex shader is used to
    process incoming vertex values rather than the fixed-function vertex
    processing described in section 2.11 through 2.14.  In particular,
    ..."

 -- Section 2.20.5 "Required State" (page 109) 

    Change the last paragraph to read:

    "Additionally, four unsigned integers (initially all zero) are
    required to hold the each respective name of the current vertex
    shader program, current geometry shader program, current fragment
    shader program, and active program respectively."

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

 -- Section 3.12 "Fragment Shaders" (page 231) 

    Replace the second to the last paragraph with:

    "When the current fragment shader program object currently includes
    a fragment shader, its fragment shader is considered active, and is
    used to process fragments.  If the fragment shader program object
    has no fragment shader, or no fragment shader program object is
    currently in use, the fixed-function fragment processing operations
    described in the previous sections are used."

 -- Section 3.12.1 "Shader Variables" (page 232) 

    Add this paragraph after the third paragraph:

    "User-defined varying values are well-defined only when the fragment
    shader program object and the preceding programmable shading stage,
    either the geometry shader stage if the geometry shader program
    object contains geometry shader or else the vertex shader stage
    if the vertex shader program object contains a vertex shader, are
    the same program object.  So user-defined varying values are only
    well-defined when both the varying variable's output shader and
    input shader are the same program object.

    In order to ensure well-defined behavior between a fragment shader
    program with a different preceding geometry shader program or
    vertex shader program when the current geometry shader program is
    zero, applications must use the built-in varying variables such
    as gl_TexCoord[0].  If the current fragment shader program object
    uses user-defined input varying variables when the preceded current
    geometry shader program is not the same program object or, in the
    case the geometry shader program is zero, the preceding current
    vertex shader program object is not the same program object, then
    the values of such input varying variables are undefined.

    The state of user-defined varying inputs to a fragment shader
    are undefined /even if/ the preceding shader has varying outputs
    that match the same name and type of the subsequent shader.
    Implementations are encouraged but not required to force these
    undefined input varying variables to zero."

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

    None

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

    None

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

 -- Section 5.4 "Display Lists" (page 311) 

    Add "CreateShaderProgramEXT" to the "Program and shader objects"
    list of commands that cannot be compiled into a display list but
    are instead executed immediately.

Additions to the AGL/GLX/WGL Specifications

    None

Additions to the OpenGL Shading Language

    None

Additions to the ARB_geometry_shader4 specification

 -- Section 2.16, Geometry Shaders

    Replace the 3rd and 4th paragraphs to read:

    "Geometry shaders are created as described in section 2.15.1 using a
    type parameter of GEOMETRY_SHADER_ARB. They are attached to and used
    in program objects as described in section 2.15.2. When a geometry
    shader program object currently in use includes a geometry shader,
    its geometry shader is considered active, and is used to process
    primitives. If the geometry shader program object has no geometry
    shader, or no program object is in use, this new primitive processing
    pipeline stage is bypassed.

    A program object that includes a geometry shader without a vertex
    shader must only use built-in input varying variables; otherwise
    a link error may occur."

 -- Section 2.16.4, Geometry Shader Execution Environment

    Change the first paragraph to read:

    "If a successfully linked program object that contains a geometry shader is
    made current as the geometry shader program object by calling
    UseShaderProgramEXT with a type of GL_GEOMETRY_SHADER_ARB, the
    executable version of the geometry shader is used to process
    primitives resulting from the primitive assembly stage."

    Add these paragraphs to the end of the section:

    "User-defined varying values are well-defined only when the geometry
    shader program object and the preceding vertex shader program object
    are the same program object.  So user-defined varying values are only
    well-defined when both the varying variable's output shader and
    input shader are the same program object.

    In order to ensure well-defined behavior between a geometry shader
    program with a different preceding vertex shader program, applications
    must use the built-in varying variables such as gl_TexCoord[0].
    If the current geometry shader program object uses user-defined
    input varying variables when the preceded current vertex shader
    program object is not the same program object, then the values of
    such input varying variables are undefined.

    The state of user-defined varying inputs to a geometry shader
    are undefined /even if/ the preceding vertex shader has varying
    outputs that match the same name and type of the subsequent shader.
    Implementations are encouraged but not required to force these
    undefined input varying variables to zero."

GLX Protocol

    UNDER DEVELOPMENT

Errors

    UseShaderProgramEXT generates INVALID_ENUM if the type parameter is
    not one of VERTEX_SHADER, GEOMETRY_SHADER_ARB, or FRAGMENT_SHADER.

    UseShaderProgramEXT generates INVALID_OPERATION if the program
    parameter has not been successfully linked.

    UseShaderProgramEXT generates INVALID_OPERATION if transform feedback
    is active.

    ActiveProgramEXT generates INVALID_OPERATION if the program parameter
    has not been successfully linked.

    LinkProgram NO LONGER generates an INVALID_OPERATION if the program
    object has a geometry shader attached and no vertex shader attached
    as long as the geometry shader uses only built-in varying input
    variables.

Dependencies on ARB_geometry_shader4, EXT_geometry_shader4, and/or NV_geometry_shader4

    If none of ARB_geometry_shader4, EXT_geometry_shader4, or
    NV_geometry_shader4 are supported by the implementation, ignore all
    references to geometry shaders and generate an INVALID_ENUM error
    when UseShaderProgramEXT is called with the token GEOMETRY_SHADER_ARB.

New State

    Remove CURRENT_PROGRAM from table 6.30 (Program Object State) and
    append these rows:

    Get Value            Type  Get Command  Initial Value  Description               Sec     Attribute
    -------------------  ----  -----------  -------------  ------------------------  ------  ---------
    ACTIVE_PROGRAM_EXT   Z+    GetIntegerv  0              The program object        2.20.2  -
    (alias for                                             that Uniform* commands
     CURRENT_PROGRAM)                                      update
    VERTEX_SHADER        Z+    GetIntegerv  0              Name of current vertex    2.20.2  -
                                                           shader program object
    GEOMETRY_SHADER_ARB  Z+    GetIntegerv  0              Name of current geometry  2.20.2  -
                                                           shader program object
    FRAGMENT_SHADER      Z+    GetIntegerv  0              Name of current fragment  2.20.2  -
                                                           shader program object
                                                    
New Implementation Dependent State

    None

Issues

    1.  What should this extension be called?

        RESOLVED:  EXT_separate_shader_objects

        The adjective "separate" is used in several extension names
        (EXT_blend_equation_separate, EXT_blend_func_separate,
        EXT_separate_specular_color, ATI_separate_stencil) when joined
        state is made configurable separately.

        The phrase "shader_objects" refers generally to GLSL shader
        objects, matching the ARB_shader_objects name.

        Whether the name should be "separate_shader_objects"
        or "shader_objects_separate" is less clear.  The various
        "separate" extensions have different conventions as to whether
        separate is prefixed or suffixed with the separated state.
        The prefixed form is more natural to say aloud, is consistent
        with the ATI_separate_stencil naming approach, and abbreviates
        to SSO (instead of the inopportune abbreviation SOS).

    2.  What happens to a user-defined input varying variable that are
        not written by a preceding shader's write to the corresponding
        output varying variable.

        RESOLVED:  The input variable variable's value is left undefined.
        Implementations are encouraged but not required to zero the
        value.

        GLSL has a "rendezvous by name" model for connecting varying
        output variables to varying input variables of a subsequent
        shader.  With separate shaders, there's no assurance whether a
        preceding shader will write a given user-defined input varying
        variable.  HLSL9, Cg, and OpenGL assembly extension programs
        handle this situation by with "rendezvous by API resource" model.
        In GLSL terms, this means separate GLSL shaders /must/ communicate
        by built-in varying variables rather than user-defined varying
        variables.

        It is undesirable from a performance standpoint to attempt to
        support "rendezvous by name" for arbitrary separate shaders
        because the separate shaders won't be naturally compiled to
        match their varying inputs and outputs of the same name without
        a special link step.  Such a special link would introduce an
        extra validation overhead to binding separate shaders.  The link
        itself would have to be deferred until glBegin time since separate
        shaders won't match when transitioning from one set of consistent
        shaders to another.  This special link would still create errors
        or undefined behavior when the names of input and output varyings
        matched but their types did not match.

        Also the expectation from other shading APIs that support
        mix-and-match shader usage is that "rendezvous by API resource"
        is the expected norm.

        Specifying the behavior being undefined allows a future ARB
        version of this extension to be more specific without encumbering
        this extension with enforcing a specific error.

    3.  Do different program objects currently used by different shader
        types share a single name space for uniforms?

        RESOLVED:  No, different program objects have their own separate
        name space for uniforms and each has locations specific to its
        unique program object.

    4.  How do the glUniform* commands determine what program object
        to query?

        RESOLVED:  This extension introduces the active program specified
        by glActiveProgramEXT (similar to the active texture selector
        specified by glActiveTexture) to specify the selector used by
        glUniform* commands.

        This active program is simply a selector and doesn't actually
        control any rendering operation.

        The active program can be queried with glGetIntegerv with
        the GL_ACTIVE_PROGRAM_EXT token which is an alias for
        GL_CURRENT_PROGRAM.

        As an alternative to setting the GL_ACTIVE_PROGRAM_EXT selector
        with glActiveProgramEXT, applications are instead encouraged
        to use the glProgramUniform* commands introduced by the
        EXT_direct_state_access extension which do not depend on a
        selector but specify the program object with which to update
        the specified uniform location explicitly.

    5.  Do the glGetUniform* queries depend on the active program state
        (GL_ACTIVE_PROGRAM_EXT)?

        RESOLVED:  No, the glGetUniform* queries take the program
        object for the query as an explicit parameter to the query.
        These commands do not rely on a selector.

    6a. Should the fragment shader program object be allowed to changed
        within transform feedback mode?

        RESOLVED:  No, this should generate an GL_INVALID_OPERATION error.

        The OpenGL 3.0 and EXT_transform_feedback specifications say
        glUseProgram generates a GL_INVALID_OPERATION error when transform
        feedback is active.

        The rationale for this is that user-defined varying outputs from
        the vertex or geometry shader might change.

        Perhaps it is desirable to allow different shader program objects
        when transform feedback mode is active, but this extension
        doesn't change the existing GLSL error behavior.  In fact,
        glUseShaderProgramEXT generate the same error glUseProgram does.

    6b. Should the active program be allowed to changed within transform
        feedback mode?

        RESOLVED:  Yes.

        The active program simply allows uniforms to be changed but
        doesn't actually change how the graphics pipeline itself is
        configured or what programs are used for vertex, geometry,
        and fragment processing.

    7.  What if a program object contains shaders from two domains, say
        both a vertex shader and a geometry shader, and the program object
        is just used as the current fragment shader program object?

        RESOLVED:  The vertex shader within the program object is
        simply ignored.

    8.  What if a program object contains both a vertex and fragment
        shader and this program object is bound to both the current
        vertex shader and fragment shader program object but there is
        also a different geometry shader program object bound?

        RESOLVED:  This works as long as the vertex shader and fragment
        shader rely on built-in varying variables to communicate and don't
        depend on passing values between each other with user-defined
        varying variables because such variables are undefined if an
        intervening different geometry shader program object is currently
        used.  Specifically, the vertex shader will output to its
        built-in varying output variables and the different geometry
        shader program object can read those built-in varying values
        through input varying variables.  Likewise the fragment shader
        can use built-in varying input variables to get varying data
        from the different geometry shader program object.

    9.  Is glUseShaderProgramEXT allowed to be compiled within a
        display list?

        RESOLVED:  Yes, just like glUseProgram is allowed within a
        display list.

    10. Should there be some easier to use API for creating a GLSL
        program that programs a single shader type?

        RESOLVED:  Yes, see the glCreateShaderProgramEXT command.

        The existing GLSL API for creating a GLSL program involves a lot
        of steps to support multiple source strings, re-specification of
        source code, attaching and detaching multiple shader objects,
        and cross-domain linking.  These features are not particularly
        relevant for creating separate shader programs.

    11. Can glCreateShaderProgramEXT be compiled into a display list?

        RESOLVED:  No.

        glCreateShaderProgramEXT is equivalent to a sequence of commands
        that are themselves not allowed to be compiled  into a display
        list.

    12. Should glCreateShaderProgramEXT allow user-defined varyings?

        RESOLVED:   User-defined varyings are permitted (without error)
        but shouldn't be used because their behavior is not defined.

        glCreateShaderProgramEXT is likely to be used for compiling
        separate shaders.  The tenative resolution to issue 2 says the
        values of user-defined varying input varaibles are undefined if
        the preceding shader doesn't belong to the same program object.
        Since the programs returned by glCreateShaderProgramEXT are
        always for a single domain, there's no point allowing user-defined
        varyings if they can't be assumed to be well-defined.

    13. How are interpolation modifiers handled for separate shader
        programs?

        RESOLVED:  For now, interpolation modifiers aren't supported
        for separate shader object varyings.

        Future resolution:  Unfortunately GLSL only provides interpolation
        modifiers for user-defined varyings which aren't well-defined
        for separate shader programs.

        In the short-term, interpolation modifiers aren't commonly used
        so not supporting interpolation modifiers for seperate GLSL
        shader programs is probably acceptable.

        Long-term, GLSL can be extended with #pragma constructs that
        specify to the compiler the interpolation modifier for a given
        fragment shader built-in varying.  Something like:

            #pragma interpolation(gl_TexCoord[0], centroid)
            #pragma interpolation(gl_TexCoord[1], flat)
            #pragma interpolation(gl_TexCoord[2], smooth)
            #pragma interpolation(gl_TexCoord[3], invariant)
            #pragma interpolation(gl_TexCoord[4], noperspective)

        This pragma is only legal within a fragment shader compilation
        unit.  The pragma can be specified multiple times, but
        inconsistent specification of a specific built-in varying's
        interpolation is not allowed.

        Alternatively, this extenion could add new built-in input varying
        variables for the fragment shader:

            // TexCoord category
            varying in centroid               vec4  gl_CentroidTexCoord[];
            varying in centroid noperspective vec4  gl_CentroidNoPerspectiveTexCoord[];
            varying in float                  vec4  gl_FlatTexCoord[];
            varying in noperspective          vec4  gl_NoPerspectiveTexCoord[];
            varying in                        ivec4 gl_IntTexCoord[];

            // Color category
            varying in centroid               vec4  gl_CentroidColor;

            // Secondary color category
            varying in centroid               vec4  gl_CentroidSecondaryColor;

            // Fog category
            varying in centroid               vec4  gl_CentroidFogFragCoord;

        It would be an error to use a varying from more than one category
        in a single program.

    14. Should glLinkProgram work to re-link a shader created with
        glCreateShaderProgramEXT?

        RESOLVED: NO because the shader created by glCreateShaderProgram
        is detached and deleted as part of the glCreateShaderProgramEXT
        sequence.  This means if you call glLinkProgram on a program
        returned from glCreateShaderProgram, you'll find the re-link
        fails because no shader object is attached.

        An application is free to attach one or more new shader objects
        to the program and then relink would work.

        This is fine because re-linking isn't necessary/expected.

    15. Wouldn't re-linking be necessary if the application wanted to
        use glBindAttribLocation to assign a user-defined attribute to
        a specific vertex attribute?

        RESOLVED:  Yes and that's a problem if glCreateShaderProgramEXT
        is used because the shader object is detached and deleted.

        User-defined attributes will work when glCreateShaderProgramEXT
        is used to easily create a vertex shader program, but the
        appliation must be satisfied with the implementation-dependent
        linker-assigned user-defined attributes returned by
        glGetAttribLocation.

        We could provide a new set of built-in attributes that correspond
        to declared as:

            attribute vec4 gl_VertexAttrib[];

        How would these attributes map to the other built-in attributes?
        That would depend on the implementation.  As with ARB_vertex_program,
        some implementations could choose to alias such generate vertex attributes
        with conventional vertex attributes (color, fog coord, etc.) or
        an implementation could treat the generic attributes as disjoint
        from the conventional vertex attributes.

        If this is unsatisfactory, the solution is to avoid using
        glCreateShaderProgramEXT and instead use the traditional GLSL
        approach for creating programs (create shader, compile shader,
        attach shader, bind attributes, link shader, use shader).

        Demonstrating how to workaround this particular issue, here's
        an example of creating and using a vertex shader for use with
        separate shader objects that includes explicit binding of output
        varyings to fragment data locations.  First the shader:
        
          varying in vec4 attribA;
          varying in vec4 attribB;
          void main()
          {
            gl_Position = ftransform();
            gl_FrontColor = attribA;
            gl_BackColor = attribB;
          }
          
        Now creating and using a linked program from this shader where
        attribA is initialized by vertex attribute 5 and attribB is
        initialized by vertex attribute 7.

          const GLuint shader = glCreateShader(GL_VERTEX_SHADER);
          if (shader) {
              const GLint len = (GLint) strlen(aboveShaderString);
              glShaderSource(shader, 1, &aboveShaderString, &len);
              glCompileShader(shader);
              const uint program = glCreateProgram();
              if (program) {
                  GLint compiled = FALSE;
                  glGetShaderiv(shader, COMPILE_STATUS, &compiled);
                  if (compiled) {
                      glAttachShader(program, shader);

                      // Crucial code that glCreateShaderProgramEXT doesn't do
                      glBindAttribLocation(program, 5, "attribA");
                      glBindAttribLocation(program, 7, "attribB");

                      glLinkProgram(program);
                      glDetachShader(program, shader);

                      // Show this program can actually be used as a vertex shader
                      glUseShaderProgramEXT(GL_VERTEX_SHADER, program);
                  }
              }
              glDeleteShader(shader);
              return program;
          } else {
              return 0;
          }

        Optionally, the glDetachShader and glDeleteShader commands could
        be removed to allow this program to be re-linked after different
        glBindAttribLocation calls.

    16. Can you use glBindFragDataLocation to direct varying output
        variables from a fragment shader program created by
        glCreateShaderProgramEXT to specific color buffers?

        RESOLVED: NO for much the same reason you can't do this with
        attributes as described in issue 15.  But you could create the
        program with the standard GLSL creation process where you attach
        your own shaders and relink.

        For fragment shader programs created with
        glCreateShaderProgramEXT, there is already the gl_FragData[]
        builtin to output to numbered color buffers.  For integer
        framebuffers, we would need to add:

            varying out ivec4 gl_IntFragData[];

        User-defined output fragment shader varyings can still be used
        as long as the application is happy with the linker-assigned
        locations.

        Demonstrating how to workaround this particular issue, here's
        an example of creating and using a fragment shader for use with
        separate shader objects that includes explicit binding of output
        varyings to fragment data locations.  First the shader:

          varying out ivec4 bufferA;
          varying out ivec4 bufferB;
          void main()
          {
            bufferA = ivec4(1,2,3,4);
            bufferB = ivec4(5,6,7,8);
          }

        Now creating and using a linked program from this shader where
        bufferA outputs to color buffer 0 and bufferB outputs to color
        buffer 1:

          const GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
          if (shader) {
              const GLint len = (GLint) strlen(aboveShaderString);
              glShaderSource(shader, 1, &aboveShaderString, &len);
              glCompileShader(shader);
              const uint program = glCreateProgram();
              if (program) {
                  GLint compiled = FALSE;
                  glGetShaderiv(shader, COMPILE_STATUS, &compiled);
                  if (compiled) {
                      glAttachShader(program, shader);

                      // Crucial code that glCreateShaderProgramEXT doesn't do
                      glBindFragDataLocation(program, 0, "bufferA");
                      glBindFragDataLocation(program, 1, "bufferB");

                      glLinkProgram(program);
                      glDetachShader(program, shader);

                      // Show this program can actually be used as a fragment shader
                      glUseShaderProgramEXT(GL_FRAGMENT_SHADER, program);
                  }
              }
              glDeleteShader(shader);
              return program;
          } else {
              return 0;
          }

        Optionally, the glDetachShader and glDeleteShader could be
        removed to allow this program to be re-linked after different
        glBindFragDataLocation calls.

    17. Can you output varyings from a seperate shader program created
        with glCreateShaderProgramEXT?

        RESOLVED:  No.

        glTransformFeedbackVaryings requires a re-link to take effect on a
        program.  glCreateShaderProgramEXT detaches and deletes the shader
        object use to create the program so a glLinkProgram will fail.

        You can still create a vertex or geometry shader program
        with the standard GLSL creation process where you could use
        glTransformFeedbackVaryings and glLinkProgram.

    18. I just don't get it?  Why is it such a big deal to just require
        apps to link all their vertex and fragment shaders together?
        Please explain a situation where mix-and-match shaders is
        substantially better than GLSL as it exists without this
        extension?

        RESOLUTION:  Consider the (not uncommon) case of a vertex shader
        for skinning an character.  The vertex shader is used in four
        distinct types of rendering passes, each using the one vertex
        shader but different fragment shaders.

        For GLSL today, this situation today requires 4 program objects,
        each containing the one vertex shader paired with each one of
        the fragment shaders.

        The one vertex shader has an array of dozens of skinning matrices
        along with numerous other uniform parameters.

        Each fragment shader has its own different set of uniforms too.

        Each GLSL program object has its own (combined) set of GLuint
        locations for the active uniforms of the vertex and fragment
        shaders objects linked into the particular program object.

        The locations for a given program object are arbitrary and
        the location values of two distinct program objects have no
        correlation.  This is true even when they each link in the same
        vertex shader (or alternatively same fragment shader).

        Now the application is saddled with the burden of managing
        distinct location values for the same vertex shader skinning
        matrices and other uniform variables as well as making sure
        the values of these variables are mirroed over all four program
        objects containing the skinning vertex shader.

        What's worse is despite all the program objects being loaded
        with the same vertex shader uniform variables for skinning, the
        driver is exceedingly unlikely to recoginize that binding from
        one of these program objects to another is going to result in
        no actual vertex shader state change.  Noticing that the uniform
        vertex shader variables are changing in lock-step over a series
        of program objects (when the uniform fragment shader variables
        ARE allowed to diverge) is exceedingly expensive.

        This situation is simple to optimize with mix-and-match shaders
        because there is just a single vertex shader to worry about.
        It's only the current fragment shader program that is changing
        so only the fragment shader state must be updated/re-validated.

        It's also much easier and less expensive for the application to
        update the vertex shader state because there is just one copy
        of it to update.

    19. In case of indirect rendering, should glCreateShaderProgramEXT
        explicitly send string length parameter to server?
        
        PROPOSED: Yes. Although source code passed to
        glCreateShaderProgramEXT is NUL terminated, the server can not
        safely rely on the client to terminate the string so it must
        add the NUL terminator before passing the protocol buffer to
        the GL command processor. The string length is needed to do this
        accurately.

    20. Can glCreateShaderProgramEXT support command larger than the 
        maximum command length supported by a single command?
 
        PROPOSED: Yes. Source code passed to glCreateShaderProgramEXT is
        unbounded. Command length can be more than the maximum command
        length supported by a single command. Support for "large single"
        command needs to be added.
        
         

Revision History

    Rev.    Date    Author    Changes
    ----  --------  --------  ----------------------------------------
    1     11/06/08  mjk       Initial revision
    2     11/10/08  mjk       add glCreateShaderProgramEXT
    3     11/12/08  mjk       fixed glCreateShaderProgramEXT
                              add issues 12 and 13
    4     11/14/08  mjk       issues 13 through 17
    5     12/03/08  mjk       glActiveProgram replaces
                              GL_UNIFORM_SHADER_EXT
    6     04/01/09  mjk       corrections from Jason Green
    7     08/12/09  mjk       Marked as shipping, resolve and
                              improve issues 15 & 16
    8     09/09/09  mjk       Assign number
    9     09/09/09  mjk       Fix transposed page number
    10    24/02/10  srahman   added glx protocol for
                              glCreateShaderProgramEXT
                              added issues 19 and 20 
    11    03/07/13  Jon Leech Added note about the unrelated OpenGL ES
                              extension of the same name.
