Name ARB_separate_shader_objects Name Strings GL_ARB_separate_shader_objects Contact Mark Kilgard, NVIDIA (mjk 'at' nvidia.com) Greg Roth, NVIDIA (groth 'at' nvidia.com) Pat Brown, NVIDIA (pbrown 'at' nvidia.com) Contributors Bruce Merry, ARM Daniel Koch, TransGaming Eric Werness, NVIDIA Graham Sellers, AMD Greg Roth, NVIDIA Jason Green, TransGaming John Kessenich, Intel Jon Leech Kevin Rogovin Nick Haemel, AMD Robert Ohannessian Notice Copyright (c) 2010-2013 The Khronos Group Inc. Copyright terms at http://www.khronos.org/registry/speccopyright.html Specification Update Policy Khronos-approved extension specifications are updated in response to issues and bugs prioritized by the Khronos OpenGL Working Group. For extensions which have been promoted to a core Specification, fixes will first appear in the latest version of that core Specification, and will eventually be backported to the extension document. This policy is described in more detail at https://www.khronos.org/registry/OpenGL/docs/update_policy.php Status Complete. Approved by the ARB on June 9, 2010. Approved by the Khronos Board of Promoters on July 23, 2010. Version Last Modified Date: 1 August 2011 Version: 25 Number ARB Extension #97 Dependencies Written based on the wording of the OpenGL 4.0 Compatibility Profile (March 11, 2010) specification. Written based on the wording of The OpenGL Shading Language 4.00.8 (March 10, 2010) specification. This extension requires OpenGL 2.0 or ARB_shader_objects. This extension interacts with OpenGL 4.0 (Core Profile). This extension interacts with GLSL 1.40 (and earlier). This extension interacts with ARB_geometry_shader4, EXT_geometry_shader4, and/or NV_geometry_shader4. This extension depends on ARB_explicit_attrib_location. This extension interacts with ARB_tessellation_shader or OpenGL 4.0. This extension interacts with GL_ARB_gpu_shader_fp64 or OpenGL 4.0. This extension interacts with ARB_explicit_attrib_location, ARB_vertex_attrib_64bit, OpenGL 3.3, and OpenGL 4.1. This extension interacts with the EXT_separate_shader_objects extension. This extension interacts with ARB_vertex_program, ARB_fragment_program, NV_gpu_program4 and related assembly extensions. Overview Conventional GLSL requires multiple shader stages (vertex, fragment, geometry, tessellation control, and tessellation evaluation) to be linked into a single monolithic program object to specify a GLSL shader for each stage. While GLSL's monolithic approach has some advantages for optimizing shaders as a unit that span multiple stages, all existing GPU hardware supports the more flexible mix-and-match approach. Shaders written for HLSL9, Cg, the prior OpenGL assembly program extensions, and game console favor a more flexible "mix-and-match" approach to specifying shaders independently for these different shader stages. 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 extension adopts a "mix-and-match" shader stage model for GLSL allowing multiple different GLSL program objects to be bound at once each to an individual rendering pipeline stage independently of other stage bindings. This allows program objects to contain only the shader stages that best suit the applications needs. This extension introduces the program pipeline object that serves as a container for the program bound to any particular rendering stage. It can be bound, unbound, and rebound to simply save and restore the complete shader stage to program object bindings. Like framebuffer and vertex array objects, program pipeline objects are "container" objects that are not shared between contexts. To bind a program object to a specific shader stage or set of stages, UseProgramStages is used. The VERTEX_SHADER_BIT, GEOMETRY_SHADER_BIT, FRAGMENT_SHADER_BIT, TESS_CONTROL_SHADER_BIT, and TESS_EVALUATION_SHADER_BIT tokens refer to the conventional vertex, geometry, fragment, tessellation control and tessellation evaluation stages respectively. ActiveShaderProgram specifies the program that Uniform* commands will update. While ActiveShaderProgram allows the use of conventional Uniform* commands to update uniform variable values for separable program objects, this extension provides a preferrable interface in a set of ProgramUniform* commands that update the same uniform variables but take a parameter indicating the program object to be updated, rather than updating the currently active program object. These commands mirror those introduced in EXT_direct_state_access. While glActiveShaderProgram provides a selector for setting and querying uniform values of a program object, the glProgramUniform* commands provide a selector-free way to modify uniforms of a GLSL program object without an explicit bind. This selector-free model reduces API overhead and provides a cleaner interface for applications. 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. This extension builds on the proof-of-concept provided by EXT_separate_shader_objects which demonstrated that separate shader objects can work for GLSL. EXT_separate_shader_objects was a response to repeated requests for this functionality from 3D developers. This ARB version addresses several "loose ends" in the prior EXT extension. In particular, it allows user-defined varyings with explicitly defined locations or implicitly assigned locations. This ARB extension extends the GLSL language's use of layout qualifiers to provide cross-stage interfacing. IP Status No known IP claims. New Procedures and Functions void UseProgramStages(uint pipeline, bitfield stages, uint program); void ActiveShaderProgram(uint pipeline, uint program); uint CreateShaderProgramv(enum type, sizei count, const char **strings); void BindProgramPipeline(uint pipeline); void DeleteProgramPipelines(sizei n, const uint *pipelines); void GenProgramPipelines(sizei n, uint *pipelines); boolean IsProgramPipeline(uint pipeline); void ProgramParameteri(uint program, enum pname, int value); void GetProgramPipelineiv(uint pipeline, enum pname, int *params); void ProgramUniform1i(uint program, int location, int x); void ProgramUniform2i(uint program, int location, int x, int y); void ProgramUniform3i(uint program, int location, int x, int y, int z); void ProgramUniform4i(uint program, int location, int x, int y, int z, int w); void ProgramUniform1ui(uint program, int location, uint x); void ProgramUniform2ui(uint program, int location, uint x, uint y); void ProgramUniform3ui(uint program, int location, uint x, uint y, uint z); void ProgramUniform4ui(uint program, int location, uint x, uint y, uint z, uint w); void ProgramUniform1f(uint program, int location, float x); void ProgramUniform2f(uint program, int location, float x, float y); void ProgramUniform3f(uint program, int location, float x, float y, float z); void ProgramUniform4f(uint program, int location, float x, float y, float z, float w); void ProgramUniform1d(uint program, int location, double x); void ProgramUniform2d(uint program, int location, double x, double y); void ProgramUniform3d(uint program, int location, double x, double y, double z); void ProgramUniform4d(uint program, int location, double x, double y, double z, double w); void ProgramUniform1iv(uint program, int location, sizei count, const int *value); void ProgramUniform2iv(uint program, int location, sizei count, const int *value); void ProgramUniform3iv(uint program, int location, sizei count, const int *value); void ProgramUniform4iv(uint program, int location, sizei count, const int *value); void ProgramUniform1uiv(uint program, int location, sizei count, const uint *value); void ProgramUniform2uiv(uint program, int location, sizei count, const uint *value); void ProgramUniform3uiv(uint program, int location, sizei count, const uint *value); void ProgramUniform4uiv(uint program, int location, sizei count, const uint *value); void ProgramUniform1fv(uint program, int location, sizei count, const float *value); void ProgramUniform2fv(uint program, int location, sizei count, const float *value); void ProgramUniform3fv(uint program, int location, sizei count, const float *value); void ProgramUniform4fv(uint program, int location, sizei count, const float *value); void ProgramUniform1dv(uint program, int location, sizei count, const double *value); void ProgramUniform2dv(uint program, int location, sizei count, const double *value); void ProgramUniform3dv(uint program, int location, sizei count, const double *value); void ProgramUniform4dv(uint program, int location, sizei count, const double *value); void ProgramUniformMatrix2fv(uint program, int location, sizei count, boolean transpose, const float *value); void ProgramUniformMatrix3fv(uint program, int location, sizei count, boolean transpose, const float *value); void ProgramUniformMatrix4fv(uint program, int location, sizei count, boolean transpose, const float *value); void ProgramUniformMatrix2dv(uint program, int location, sizei count, boolean transpose, const double *value); void ProgramUniformMatrix3dv(uint program, int location, sizei count, boolean transpose, const double *value); void ProgramUniformMatrix4dv(uint program, int location, sizei count, boolean transpose, const double *value); void ProgramUniformMatrix2x3fv(uint program, int location, sizei count, boolean transpose, const float *value); void ProgramUniformMatrix3x2fv(uint program, int location, sizei count, boolean transpose, const float *value); void ProgramUniformMatrix2x4fv(uint program, int location, sizei count, boolean transpose, const float *value); void ProgramUniformMatrix4x2fv(uint program, int location, sizei count, boolean transpose, const float *value); void ProgramUniformMatrix3x4fv(uint program, int location, sizei count, boolean transpose, const float *value); void ProgramUniformMatrix4x3fv(uint program, int location, sizei count, boolean transpose, const float *value); void ProgramUniformMatrix2x3dv(uint program, int location, sizei count, boolean transpose, const double *value); void ProgramUniformMatrix3x2dv(uint program, int location, sizei count, boolean transpose, const double *value); void ProgramUniformMatrix2x4dv(uint program, int location, sizei count, boolean transpose, const double *value); void ProgramUniformMatrix4x2dv(uint program, int location, sizei count, boolean transpose, const double *value); void ProgramUniformMatrix3x4dv(uint program, int location, sizei count, boolean transpose, const double *value); void ProgramUniformMatrix4x3dv(uint program, int location, sizei count, boolean transpose, const double *value); void ValidateProgramPipeline(uint pipeline ); void GetProgramPipelineInfoLog(uint pipeline, sizei bufSize, sizei *length, char *infoLog); New Tokens Accepted by parameter to UseProgramStages: VERTEX_SHADER_BIT 0x00000001 FRAGMENT_SHADER_BIT 0x00000002 GEOMETRY_SHADER_BIT 0x00000004 TESS_CONTROL_SHADER_BIT 0x00000008 TESS_EVALUATION_SHADER_BIT 0x00000010 ALL_SHADER_BITS 0xFFFFFFFF Accepted by the parameter of ProgramParameteri and GetProgramiv: PROGRAM_SEPARABLE 0x8258 Accepted by parameter to GetProgramPipelineiv: ACTIVE_PROGRAM 0x8259 Accepted by the parameter of GetBooleanv, GetIntegerv, GetInteger64v, GetFloatv, and GetDoublev: PROGRAM_PIPELINE_BINDING 0x825A Additions to Chapter 2 of the OpenGL 4.0 Compatibility Profile Specification (OpenGL Operation): -- Section 2.14 "Vertex Shaders" (page 89) Modify the third paragraphs: To use a vertex shader, shader source code is first loaded into a shader object and then compiled. A shader object corresponds to a stage in the rendering pipeline referred to as its shader stage or type. One or more vertex shader objects are attached to a program object. The program object is then linked, which generates executable code from all the compiled shader objects attached to the program. When program objects are bound to a shader stage, they become the current program object for that stage. When the current program object for the vertex stage includes a vertex shader, it is considered the active program object for the vertex stage. The current program object for all stages may be set at once using a single unified program object, or the current program object may be set for each stage individually using a separable program object where different separable program objects may be current for other stages. The set of separable program objects current for all stages are collected in a program pipeline object that must be bound for use. When a linked program object is made active for the vertex stage, the executable code for the vertex shaders it contains is used to process vertices." Modify the last sentence in the fourth paragraph: "... A single program object can contain all of vertex, tessellation control, tessellation evaluation, geometry, and fragment shaders, or any subset thereof." Modify the fifth paragraph: "When the program object currently in use for the vertex stage includes a vertex shader, its vertex shader is considered active and is used to process vertices. If the current vertex stage program object has no vertex shader or no program object is current for the vertex stage, ..." -- Section 2.14.2 "Program Objects" (page 91) In the list of linking failures following the description of LinkProgram, modify the bullets reading "the program contains no objects to form a vertex shader" when using a tessellation control, tessellation evaluation, or geometry shader (pp. 92-93) to read: - the program is not separable and contains no objects to form a vertex shader; Modify the eighth paragraph: If a program has been successfully linked by LinkProgram, it can be made part of the current rendering state for all shader stages with the command void UseProgram(uint program); If is non-zero, this command will make the current program object. This will install executable code as part of the current rendering state for each shader stage present when the program was last successfully linked. If UseProgram is called with set to zero, then there is no current program object. If has not been successfully linked, the error INVALID_OPERATION is generated and the current rendering state is not modified. Insert before the last paragraph, p. 93: The executable code for an individual shader stage is taken from the current program for that stage. If there is a current program object established by UseProgram, that program is considered current for all stages. Otherwise, if there is a bound program pipeline object (section 2.14.PPO), the program bound to the appropriate stage of the pipeline object is considered current. If there is no current program object or bound program pipeline object, no program is current for any stage. The current program for a stage is considered active if it contains executable code for that stage; otherwise, no program is considered active for that stage. If there is no active program for the vertex or fragment shader stages, [[ Compatibility Profile ]] fixed-function vertex and/or fragment processing will be used to process vertices and/or fragments. [[ Core Profile ]] the results of vertex and/or fragment processing will be undefined. However, this is not an error. [[ End Profile-Specific Language ]] If there is no active program for the tessellation control, tessellation evaluation, or geometry shader stages, those stages are ignored. Insert at the end of the section, p. 94 (note: this will be inserted below several of the edits that follow). "The command uint CreateShaderProgramv(enum type, sizei count, const char **strings); creates a stand-alone program from an array of null-terminated source code strings for a single shader type. CreateShaderProgramv is equivalent to the following command sequence: const uint shader = CreateShader(type); if (shader) { ShaderSource(shader, count, strings, NULL); CompileShader(shader); const uint program = CreateProgram(); if (program) { int compiled = FALSE; GetShaderiv(shader, COMPILE_STATUS, &compiled); ProgramParameteri(program, PROGRAM_SEPARABLE, TRUE); if (compiled) { AttachShader(program, shader); LinkProgram(program); DetachShader(program, shader); } append-shader-info-log-to-program-info-log } DeleteShader(shader); return program; } else { return 0; } The program may not actually link if the output variables in the shader attached to the final stage of the linked program take up too many locations. If this situation arises, the info log may explain this. Because no shader is returned by CreateShaderProgramv 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." Modify first and second paragraphs, p. 94: If a program object that is active for any shader stage is re-linked successfully, the LinkProgram command will install the generated executable code as part of the current rendering state for all shader stages where the program is active. Additionally, the newly generated executable code is made part of the state of any program pipeline for all stages where the program is attached. If a program object that is active for any shader stage is re-linked unsuccessfully, the link status will be set to FALSE, but existing executables and associated state will remain part of the current rendering state until a subsequent call to UseProgram, UseProgramStages, or BindProgramPipeline removes them from use. If such a program is attached to any program pipeline object, the existing executables and associated state will remain part of the program pipeline object until a subsequent call to UseProgramStages removes them from use. An unsuccessfully linked program may not be made part of the current rendering state by UseProgram or added to program pipeline objects by UseProgramStages until it is successfully re-linked. If such a program was attached to a program pipeline at the time of a failed link, its existing executable may still be made part of the current rendering state indirectly by BindProgramPipeline. Modify the last paragraph of the section, p. 94: "If is not current for any GL context, is not the active program for any program pipeline object, and is not the current program for any stage of any program pipeline object, it is deleted immediately. Otherwise, program is flagged ..." Insert prior to the description of DeleteProgram, p. 94 (note: this text is inserted above the previous edit): "Program parameters control aspects of how the program is linked, executed, or stored. To set a program parameter, call void ProgramParameteri(uint program, enum pname, int value) identifies which parameter to set for program object . holds the value being set. If is PROGRAM_SEPARABLE, must be TRUE or FALSE and indicates whether the can be bound for individual pipeline stages via UseProgramStages after it is next linked. If is any other value, the error INVALID_ENUM is generated. -- New section 2.14.PPO "Program Pipeline Objects" after 2.14.2 "Program Objects" Instead of packaging all shader stages into a single program object, shader types might be contained in multiple program objects each consisting of part of the complete pipeline. A program object may even contain only a single shader stage. This facilitates greater flexibility when combining different shaders in various ways without requiring a program object for each combination. Program bindings associating program objects with shader types are collected to form a program pipeline object. The command void GenProgramPipelines(sizei n, uint *pipelines); returns previously unused program pipeline object names in . These names are marked as used, for the purposes of GenProgramPipelines only, but they acquire state only when they are first bound. Program pipeline objects are deleted by calling void DeleteProgramPipelines(sizei n, const uint *pipelines); contains names of program pipeline objects to be deleted. Once a program pipeline object is deleted, it has no contents and its name becomes unused. If an object that is currently bound is deleted, the binding for that object reverts to zero and no program pipeline object becomes current. Unused names in are silently ignored, as is the value zero. A program pipeline object is created by binding a name returned by GenProgramPipelines with the command void BindProgramPipeline(uint pipeline); is the program pipeline object name. The resulting program pipeline object is a new state vector, comprising ACTIVE_PROGRAM, VERTEX_SHADER, GEOMETRY_SHADER, FRAGMENT_SHADER, TESS_CONTROL_SHADER, and TESS_EVALUATION_SHADER. BindProgramPipeline may also be used to bind an existing program pipeline object. If the bind is successful, no change is made to the state of the bound program pipeline object, and any previous binding is broken. If BindProgramPipeline is called with set to zero, then there is no current program pipeline object. If no current program object has been established by UseProgram, the program objects used for each shader stage and for uniform updates are taken from the bound program pipeline object, if any. If there is a current program object established by UseProgram, the bound program pipeline object has no effect on rendering or uniform updates. When a bound program pipeline object is used for rendering, individual shader executables are taken from its program objects as described in the discussion of UseProgram in section 2.14.2. BindProgramPipeline fails and an INVALID_OPERATION error is generated if is not zero or a name returned from a previous call to GenProgramPipelines, or if such a name has since been deleted with DeleteProgramPipelines. The executables in a program object associated with one or more shader stages can be made part of the program pipeline state for those shader stages with the command: void UseProgramStages(uint pipeline, bitfield stages, uint program); where is the program pipeline object to be updated, is the bitwise OR of accepted constants representing shader stages, and is the program object from which the executables are taken. The bits set in indicate the program stages for which the program object named by becomes current. These stages may include tessellation control, tessellation evaluation, vertex, geometry, or fragment indicated by TESS_CONTROL_- SHADER_BIT, TESS_EVALUATION_SHADER_BIT, VERTEX_SHADER_BIT, GEOMETRY_- SHADER_BIT, or FRAGMENT_SHADER_BIT respectively. The constant ALL_- SHADER_BITS indicates is to be made current for all shader stages. If refers to a program object with a valid shader attached for an indicated shader stage, this call installs the executable code for that stage in the indicated program pipeline object state. If UseProgramStages is called with set to zero or with a program object that contains no executable code for a given stages, it is as if the pipeline object has no programmable stage configured for the indicated shader stages. If is not the special value ALL_SHADER_BITS and has a bit set that is not recognized, the error INVALID_VALUE is generated. If the program object named by was linked without the PROGRAM_SEPARABLE parameter set or was not linked successfully, the error INVALID_OPERATION is generated and the corresponding shader stages in the program pipeline object are not modified. If is a name that has been generated (without subsequent deletion) by GenProgramPipelines, but refers to a program pipeline object that has not been previously bound, the GL first creates a new state vector in the same manner as when BindProgramPipeline creates a new program pipeline object. If is not a name returned from a previous call to GenProgramPipelines or if such a name has since been deleted by DeleteProgramPipelines, an INVALID_- OPERATION error is generated. The command void ActiveShaderProgram(uint pipeline, uint program); sets the linked program named by to be the active program (discussed later in the secion 2.14.4) for the program pipeline object . If has not been successfully linked, the error INVALID_OPERATION is generated and active program is not modified. If is a name that has been generated (without subsequent deletion) by GenProgramPipelines, but refers to a program pipeline object that has not been previously bound, the GL first creates a new state vector in the same manner as when BindProgramPipeline creates a new program pipeline object. If is not a name returned from a previous call to GenProgramPipelines or if such a name has since been deleted by DeleteProgramPipelines, an INVALID_- OPERATION error is generated. Shader Interface Matching When multiple shader stages are active, the outputs of one stage form an interface with the inputs of the next stage. At each such interface, shader inputs are matched up against outputs from the previous stage: * An output block is considered to match an input block in the subsequent shader if the two blocks have the same block name, and the members of the block match exactly in name, type, qualification, and declaration order. * An output variable is considered to match an input variable in the subequent shader if: * the two variables match in name, type, and qualification; or * the two variables are declared with the same location layout qualifier and match in type and qualification. Variables or block members declared as structures are considered to match in type if and only if structure members match in name, type, qualification, and declaration order. Variables or block members declared as arrays are considered to match in type only if both declarations specify the same element type and array size. The rules for determining if variables or block members match in qualification are found in the OpenGL Shading Language Specification. Tessellation control shader per-vertex output variables and blocks and tessellation control, tessellation evaluation, and geometry shader per-vertex input variables and blocks are required to be declared as arrays, with each element representing input or output values for a single vertex of a multi-vertex primitive. For the purposes of interface matching, such variables and blocks are treated as though they were not declared as arrays. For program objects containing multiple shaders, LinkProgram will check for mismatches on interfaces between shader stages in the program being linked and generate a link error if a mismatch is detected. A link error will be generated if any statically referenced input variable or block does not have a matching output. If either shader redeclares the built-in array gl_ClipDistance[] ((compatibility profile only: or gl_TexCoord[])), the array must have the same size in both shaders. ((compatibility profile only: If either shader redeclares built-in input or output color variables, they must have matching interpolation qualifiers, as described in the OpenGL Shading Language Specification.)) With separable program objects, interfaces between shader stages may involve the outputs from one program object and the inputs from a second program object. For such interfaces, it is not possible to detect mismatches at link time, because the programs are linked separately. When each such program is linked, all inputs or outputs interfacing with another program stage are treated as active. The linker will generate an executable that assumes the presence of a compatible program on the other side of the interface. If a mismatch between programs occurs, no GL error will be generated, but some or all of the inputs on the interface will be undefined. At an interface between program objects, the set of inputs and outputs are considered to match exactly if and only if: * The built-in input and output blocks used on the interface ("gl_PerVertex" or "gl_PerFragment") match, as described below. * Every declared input block or variable must have a matching output, as described above. * There are no output blocks or user-defined output variables declared without a matching input block or variable declaration. When the set of inputs and outputs on an interface between programs matches exactly, all inputs are well-defined unless the corresponding outputs were not written in the previous shader. However, any mismatch between inputs and outputs results in all inputs being undefined except for cases noted below. Even if an input has a corresponding output that matches exactly, mismatches on other inputs or outputs may adversely affect the executable code generated to read or write the matching variable. The inputs and outputs on an interface between programs need not match exactly when input and output location qualifiers (sections 4.3.8.1 and 4.3.8.2 of the GLSL Specification) are used. When using location qualifiers, any input with an input location qualifier will be well-defined as long as the other program writes to a matching output, as described above. The names of variables need not match when matching by location. Additionally, scalar and vector inputs with location layout qualifiers will be well-defined if there is a corresponding output satisfying all of the following conditions: * the input and output match exactly in qualification, including in the location layout qualifier; * the output is a vector with the same basic component type and has more components than the input; and * the common component type of the input and output is "int", "uint", or "float" (scalars and vectors with "double" component type are excluded). In this case, the components of the input will be taken from the first components of the matching output, and the extra components of the output will be ignored. To use any built-in input or output in the gl_PerVertex and gl_PerFragment blocks in separable program objects, shader code must redeclare those blocks prior to use. A separable program will fail to link if: * it contains multiple shaders of a single type with different redeclarations of these built-in input and output blocks; or * any shader uses a built-in block member not found in the redeclaration of that block. [[ There are two somewhat different versions of the following language -- one for the compatibility profile and the other for the core profile. ]] [[ Compatibility Profile ]] As described above, an exact interface match requires matching built-in input and output blocks. At an interface between two non-fragment shader stages, the gl_PerVertex input and output blocks are considered to match if and only if the block members members match exactly in name, type, qualification, and declaration order. At an interface involving the fragment shader stage, a gl_PerVertex output block is considered to match a gl_PerFragment input block if all of the following conditions apply: * the gl_PerVertex block includes either gl_FrontColor or gl_BackColor if and only if the gl_PerFragment block includes gl_Color; * the gl_PerVertex block includes either gl_FrontSecondaryColor or gl_BackSecondaryColor if and only if the gl_PerFragment block includes gl_SecondaryColor; * the gl_PerVertex block includes gl_FogFragCoord if and only if the gl_PerFragment block also includes gl_FogFragCoord; and * the size of gl_TexCoord[] in gl_PerVertex and gl_PerFragment is identical. At an interface between gl_PerVertex outputs and gl_PerFragment inputs, the presence or absence of any block members other than those listed immediately above does not affect interface matching. [[ Core Profile ]] As described above, an exact interface match requires matching built-in input and output blocks. At an interface between two non-fragment shader stages, the gl_PerVertex input and output blocks are considered to match if and only if the block members members match exactly in name, type, qualification, and declaration order. At an interface involving the fragment shader stage, the presence or absence of any built-in output does not affect interface matching. [[ End Profile-Specific Language ]] Built-in inputs or outputs not found in blocks do not affect interface matching. Any such built-in inputs are well-defined unless they are derived from built-in outputs not written by the previous shader stage. Program Pipeline Object State "The state required to support program pipeline objects consists of a single binding name of the current program pipeline object. This binding is initially zero indicating no program pipeline object is bound. The state of each program pipeline object consists of: * Six unsigned integers (initially all zero) are required to hold each respective name of the current vertex stage program, current geometry stage program, current fragment stage program, current tessellation control stage program, current tessellation evaluation stage program, and active program respectively. * A Boolean holding the status of the last validation attempt, initially false * An array of type char containing the information log, initially empty. * An integer holding the length of the information log" -- Section 2.14.4 "Uniform Variables" (page 97) Replace the 1st paragraph of the "Loading Uniform Variables In The Default Uniform Block" section (page 108): "To load values into the uniform variables of the active program object, use the commands ... ... If a non-zero program object is bound by UseProgram, it is the active program object whose uniforms are updated by these commands. If no program object is bound using UseProgram, the active program object of the current program pipeline object set by ActiveShader- Program is the active program object. If the current program pipeline object has no active program or there is not current program pipeline object, then there is no active program. The given values are loaded into the default ... " Change the last bullet in the "Loading Uniform Variables In The Default Uniform Block" section (page 110) to: "* if there is no active program in use." Add to the end of the subsection "Loading Uniform Variables In The Default Uniform Block" section (page 110): To load values into the uniform variables of the default uniform block of a program which may not necessarily be bound, use the commands void ProgramUniform{1234}{ifd}(uint program, int location, T value); void ProgramUniform{1234}{ifd}v(uint program, int location, sizei count, const T value); void ProgramUniform{1234}ui(uint program, int location, T value); void ProgramUniform{1234}uiv(uint program, int location, sizei count, T value); void ProgramUniformMatrix{234}{fd}v (uint program, int location, sizei count, boolean transpose, const float *value); void ProgramUniformMatrix{2x3 3x2 2x4 4x2 3x4 4x3}{fd}v (uint program, int location, sizei count, boolean transpose, const float *value); These commands operate identically to the corresponding commands above without "Program" in the command name except, rather than updating the currently active program object, these "Program" commands update the program object named by the initial parameter.The remaining parameters following the initial parameter match the parameters for the corresponding non-"Program" uniform command. If is not the name of a created program or shader object, the error INVALID_VALUE is generated. If identifies a shader object or a program object that has not been linked successfully, the error INVALID_OPERATION is generated. -- Section 2.14.4 "Subroutine Uniform Variables" (page 114) Modify the last paragraph of the section, p. 117 When the active program for a shader stage is re-linked or changed by a call to UseProgram, BindProgramPipeline, or UseProgramStages, subroutine uniforms for that stage are reset to arbitrarily chosen default functions with compatible subroutine types. -- Section 2.14.8 "Shader Execution" (page 122) Change the first paragraph: "If there is an active program object present for the vertex, tessellation control, tessellation evaluation, or geometry shader stages, the executable code for these active programs is used to process incoming vertex values rather than the fixed-function vertex processing described in sections 2.12 through 2.13. In particular, ..." Modify first paragraph of "Validation", p. 129 (replace first paragraph) It is not always possible to determine at link time if a program object can execute successfully, given that LinkProgram can not know the state of the remainder of the pipeline. Therefore validation is done when the first rendering command is issued, to determine if the set of active program objects can be executed. If the current set of active program objects cannot be executed, no primitives are processed and the error INVALID_OPERATION will be generated. Add to the list in the second paragraph of subsection "Validation" (Page 129): "* A program object is active for at least one, but not all of the shader stages that were present when the program was linked. * One program object is active for at least two shader stages and a second program is active for a shader stage between two stages for which the first program was active. * There is an active program for tessellation control, tessellation evaluation, or geometry stages with corresponding executable shader, but there is no active program with executable vertex shader. * There is not current unified program object and the current program pipeline object includes a program object that was relinked since being applied to the pipeline object via UseProgramStages with the PROGRAM_SEPARABLE parameter set to FALSE." Add after the description of ValidateProgram in subsection "Validation": "Separable program objects may have validation failures that cannot be detected without the complete program pipeline. Mismatched interfaces, improper usage of program objects together, and the same state-dependent failures can result in validation errors for such program objects. As a development aid, use the command void ValidateProgramPipeline(uint pipeline ); to validate the program pipeline object against the current GL state. Each program pipeline object has a boolean status, VALIDATE_STATUS, that is modified as a result of validation. This status can be queried with GetProgramPipelineiv (See section 6.1.18). If validation succeeded, the program pipeline object is guaranteed to execute given the current GL state. If is a name that has been generated (without subsequent deletion) by GenProgramPipelines, but refers to a program pipeline object that has not been previously bound, the GL first creates a new state vector in the same manner as when BindProgramPipeline creates a new program pipeline object. If is not a name returned from a previous call to GenProgramPipelines or if such a name has since been deleted by DeleteProgramPipelines, an INVALID_- OPERATION error is generated. -- Section 2.15 "Tessellation" (page 131) (modify second paragraph, p. 132) ... Tessellation is considered active if and only if there is an active tessellation control or tessellation evaluation program object. (modify next-to-last paragraph, p. 132) Patch primitives are not supported by pipeline stages below the tessellation evaluation shader. If there is no active tessellation evaluation program, the error INVALID_OPERATION is generated by Begin, and any command that performs an implicit Begin, if the primitive mode is PATCHES. Modify last paragraph, p. 132: "A program object or program pipeline object that includes a tessellation shader of any kind must also include a vertex shader. If the current program state has a tessellation shader but no vertex shader at Begin or any command that implicitly calls Begin, an INVALID_OPERATION error will be generated." -- Section 2.15.1 "Tessellation Control Shaders" (page 133) Change the first paragraph of "Tessellation Control Shader Execution Environment" (p. 134) "If there is an active program for the tessellation control stage, the executable version of the program's tessellation control shader is used ..." -- Section 2.15.3 "Tessellation Evaluation Shaders" (page 147) Change the first paragraph of "Tessellation Evaluation Shader Execution Environment" (p. 149) "If there is an active program for the tessellation evaluation stage, the executable version of the program's tessellation evaluation shader is used ..." -- Section 2.16, "Geometry Shaders" (page 153) Change the 4th paragraph: "A program object or program pipeline object that includes a geometry shader must also include a vertex shader. If the current program state has a geometry shader but no vertex shader at Begin or any command that implicitly calls Begin, an INVALID_OPERATION error will be generated." -- Section 2.16.1, Geometry Shader Input Primitives, p. 153 (modify first paragraph of the section) ... will generate an INVALID_OPERATION error if the primitive parameter is incompatible with the input primitive type of the geometry shader of the active geometry program object, as discussed below. -- Section 2.16.4, Geometry Shader Execution Environment Change the first paragraph: "If there is an active program for the geometry stage, the executable version of the program's geometry shader is used ..." -- Section 2.20 "Transform Feedback" (page 167) Modify first paragraph and add the subsequent paragraphs: "In transform feedback mode, attributes of the vertices of primitives passed to the transform feedback stage are written out to one or more buffer objects. The vertices are fed back after vertex color clamping, but before flatshading and clipping. The transformed vertices may be optionally discarded after being stored into one or more buffer objects, or they can be passed on down to the clipping stage for further processing. The set of attributes captured is determined when a program is linked. The data captured in transform feedback mode depends on the active programs on each of the shader stages. If a program is active for the geometry shader stage, transform feedback captures the vertices of each primitive emitted by the geometry shader. Otherwise, if a program is active for the tessellation evaluation shader stage, transform feedback captures each primitive produced by the tessellation primitive generator, whose vertices are processed by the tessellation evaluation shader. Otherwise, transform feedback captures each primitive processed by the vertex shader. If separable program objects are in use, the set of attributes captured is taken from the program object active on the last shader stage processing the primitives captured by transform feedback. The set of attributes to capture in transform feedback mode for any other program active on a previous shader stage is ignored." Add to list of INVALID_OPERATION errors on page 172 * by UseProgramStages if the program pipeline object it refers to is current and the current transform feedback object is active and not paused. * by BindProgramPipeline if the current transform feedback object is active and not paused. * by ResumeTransformFeedback if the program pipeline object being used by the current transform feedback object is not bound, any of its shader stage bindings has changed, or a single program object is active and overriding it. Additions to Chapter 3 of the OpenGL 4.0 Compatibility Profile Specification (Rasterization) -- Section 3.12 "Fragment Shaders" (page 321) 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." Additions to Chapter 4 of the OpenGL 4.0 Compatibility Profile Specification (Per-Fragment Operations and the Frame Buffer) None Additions to Chapter 5 of the OpenGL 4.0 Compatibility Profile Specification (Special Functions) -- Section 5.5 "Display Lists" (page 410) Add CreateShaderProgram, GenProgramPipelines, DeleteProgram- Pipelines, and BindProgramPipelines to the "Program and shader objects" list of commands that cannot be compiled into a display list but are instead executed immediately. Additions to Chapter 6 of the OpenGL 4.0 Compatibility Profile Specific- ation (State and State Requests) -- Section 6.1.18 "Shader and Program Queries" Add to GetProgramiv description: "If is PROGRAM_SEPARABLE, TRUE is returned if the program has been flagged for use as a separable program object that can be bound to individual shader stages with UseProgramStages." Add after GetProgramiv description: "The command boolean IsProgramPipeline(uint pipeline); returns TRUE if is the name of a program pipeline object. If is zero, or a non-zero value that is not the name of a program pipeline object, IsProgramPipeline returns FALSE. No error is generated if is not a valid program pipeline object name. The command GetProgramPipelineiv(uint pipeline, enum pname, int *params); returns properties of the program pipeline object named in . The parameter value to return is specified by . If is a name that has been generated (without subsequent deletion) by GenProgramPipelines, but refers to a program pipeline object that has not been previously bound, the GL first creates a new state vector in the same manner as when BindProgramPipeline creates a new program pipeline object. If is not a name returned from a previous call to GenProgramPipelines or if such a name has since been deleted by DeleteProgramPipelines, an INVALID_- OPERATION error is generated. If is ACTIVE_PROGRAM, the name of the active program object of the program pipeline object is returned. If is VERTEX_SHADER, the name of the current program object for the vertex shader type of the program pipeline object is returned. If is FRAGMENT_SHADER, the name of the current program object for the fragment shader type of the program pipeline object is returned. If is GEOMETRY_SHADER, the name of the current program object for the geometry shader type of the program pipeline object is returned; If is TESS_CONTROL_SHADER, the name of the current program object for the tessellation control shader type of the program pipeline object is returned; If is TESS_EVALUATION_SHADER, the name of the current program object for the tessellation evaluations shader type of the program pipeline object is returned. If is VALIDATE_STATUS, the validation status of the program pipeline object, as determined by ValidateProgramPipeline (see section 2.14.8) is returned. If is INFO_LOG_LENGTH, the length of the info log, including a null terminator, is returned. If there is no info log, zero is returned." If is not the name of an accepted parameter, an INVALID_- ENUM error is generated. Change paragraph describing GetShaderInfoLog and GetProgram: "A string that contains information about the last compilation attempt on a shader object, last link or validation attempt on a program object, or last validation attempt on a program pipeline object, called the info log, can be obtained with the commands void GetShaderInfoLog (uint shader, sizei bufSize, sizei *length, char *infoLog); void GetProgramInfoLog (uint program, sizei bufSize, sizei *length, char *infoLog); void GetProgramPipelineInfoLog (uint pipeline, sizei bufSize, sizei *length, char *infoLog); These commands return the info log string in . This string will be null-terminated. The actual number of characters written into , excluding the null terminator, is returned in . If is NULL, then no length is returned. The maximum number of characters that may be written into , including the null terminator, is specified by . The number of characters in the info log can be queried with GetShaderiv, GetProgramiv, or GetProgramPipelineiv with INFO_LOG_LENGTH. If is a shader object, the returned info log will either be an empty string or it will contain information about the last compil- ation attempt for that object. If is a program object, the returned info log will either be an empty string or it will contain information about the last link attempt or last validation attempt for that object. If is a program pipeline object, the returned info log will either be an empty string or it will contain information about the last validation attempt for that object. Additions to Appendix D of the OpenGL 4.0 Compatibility Profile Specific- ation (Shared Objects and Multiple Contexts) (modify third paragraph, p. 533, making program pipeline objects non-shared) Framebuffer, query, vertex array, and program pipeline objects are not shared. Additions to the AGL/GLX/WGL Specifications None Additions to the OpenGL Shading Language Specification, Version 4.00.8 Including the following line in a shader can be used to control the language feature described in thie extension: #extension GL_ARB_separate_shader_objects : where is as described in section 3.3. A new preprocessor #define is added to the OpenGL Shading Language: #define GL_ARB_separate_shader_objects 1 -- Section 4.3 "Storage Qualifiers" (page 32): Add to the end of the section: When comparing an output from one shader stage to an input of a second shader stage, the input and output are considered to match only if compatible storage qualifiers are used. An output declared with "out", "centroid out", "sample out", or "patch out" matches an input only if the input is declared with "in", "centroid in", "sample in", or "patch in", respectively. Additionally, an output will only match an input with identical interpolation qualifiers. [[ Note: If the GLSL specification is updated to break out "centroid", "sample", and "patch" as separate auxillary qualifiers instead of tightly coupling with "in" and "out" as in GLSL 4.00, this language should be rewritten to require that these auxillary qualifiers match (and that "in" match "out", of course). ]] -- Section 4.3.4 "Inputs" (page 36): Add to the end of the section: When an interface between shader stages is formed using shaders from two separate program objects, it is not possible to detect mismatches between inputs and outputs when the programs are linked. When there are mismatches between inputs and outputs on such interfaces, the values passed across the interface will be partially or completely undefined. Shaders can ensure matches across such interfaces either by using input and output layout qualifiers (Sections 4.3.8.1 and 4.3.8.2) or by using identical input and output declarations. Complete rules for interface matching are found in the "Shader Interface Matching" portion of section 2.14.PPO of the OpenGL Specification. -- Section 4.3.8.1 "Input Layout Qualifiers" (page 44): All shaders allow location input layout qualifiers on input variable declarations. The location layout qualifier identifier for inputs is: layout-qualifier-id location = integer-constant Only one argument is accepted. For example, layout(location = 3) in vec4 normal; establishes that the shader input is assigned to location number 3. For vertex shader inputs, the location specifies the number of the generic vertex attribute from which input values are taken. For inputs of all other shader types, the location specifies a vector number that can be used to match against outputs from a previous shader stage, even if that shader is in a different program object. If the declared input has a scalar or vector type, it will consume a single location, except for non-vertex inputs of type "dvec3" and "dvec4", which will consume two consecutive locations. Inputs of type "double" and "dvec2" will consume only a single location in all shaders. If the declared input is an array of size and each element takes up locations, it will be assigned * consecutive locations starting with the location specified. For example, layout(location = 6) in vec4 colors[3]; will establish that the input is assigned to vector location numbers 6, 7, and 8. If the declared input is an x single- or double-precision matrix, it will be assigned multiple locations starting with the location specified. The number of locations assigned for each matrix will be the same as for an -element array of -component vectors. For example, layout(location = 9) in mat4 transforms[2]; will establish that input is assigned to vector location numbers 9-16, with transforms[0] being assigned to locations 9-12 and transforms[1] being assigned to locations 13-16. If the declared input is a structure, its members will be assigned consecutive locations in the order of declaration, with the first member assigned the location specified for the structure. The number of locations consumed by a structure member is determined by applying the rules above recursively as though the structure member were declared as an input variable of the same type. For example, layout(location = 3) struct S { vec3 a; mat2 b; vec4 c[2]; } s; will assign location 3 to "s.a", locations 4 and 5 to the two column vectors of "s.b", and locations 6 and 7 to "s.c". Location layout qualifiers may be used on input variables declared as structures, but not on individual members. Location layout qualifiers may not be used on input blocks or input block members. The number of input locations available to a shader is limited. For vertex shaders, the limit is the advertised number of vertex attributes. For all other shaders, the limit is implementation-dependent and must be no less than one fourth of the advertised maximum input component count. A program will fail to link if any attached shader uses a location greater than or equal to the number of supported locations, unless device-dependent optimizations are able to make the program fit within available hardware resources. A program will fail to link if any two non-vertex shader input variables are assigned to the same location. For vertex shaders, multiple input variables may be assigned to the same location using either layout qualifiers or via the OpenGL API. However, such aliasing is intended only to support vertex shaders where each execution path accesses at most one input at each location. Implementations are permitted, but not required, to generate link errors if they detect that every path through the vertex shader executable accesses multiple inputs assigned to any single location. For all shader types, a program will fail to link if explicit location assignments leave the linker unable to find space for other variables without explicit assignments. For the purposes of determining if a non-vertex input matches an output from a previous shader stage, the location layout qualifier (if any) must match. -- Section 4.3.8.2 "Output Layout Qualifiers" (page 48) Modify the description of fragment output qualifiers. All shaders allow location output layout qualifiers on output variable declarations. The location layout qualifier identifier for outputs is: layout-qualifier-id location = integer-constant Fragment shaders allow an additional index output layout qualifiers: layout-qualifier-id location = integer-constant index = integer-constant Each of these qualifiers may appear at most once. If index is specified, location must also be specified. If index is not specified, the value 0 is used. For example, in a fragment shader, layout(location = 3) out vec4 color; will establish that the fragment shader output is assigned to fragment color 3 as the first (index zero) input to the blend equation. And, layout(location = 3, index = 1) out vec4 factor; will establish that the fragment shader output factor is assigned to fragment color 3 as the second (index one) input to the blend equation. For fragment shader outputs, the location and index specify the color output number and index receiving the values of the output. For outputs of all other shader types, the location specifies a vector number that can be used to match against inputs in a subsequent shader stage, even if that shader is in a different program object. If the declared output has a scalar or vector type, it will consume a single location, except for outputs of type "dvec3" and "dvec4", which will consume two consecutive locations. Outputs of type "double" and "dvec2" will consume only a single location in all shaders. If the declared output is an array, it will be assigned consecutive locations starting with the location specified. For example, layout(location = 2) out vec4 colors[3]; will establish that is assigned to vector location numbers 2, 3, and 4. If the declared output is an x single- or double-precision matrix, it will be assigned multiple locations starting with the location specified. The number of locations assigned will be the same as for an -element array of -component vectors. If the declared output is a structure, its members will be assigned consecutive locations in the order of declaration, with the first member assigned the location specified for the structure. The number of locations consumed by a structure member is determined by applying the rules above recursively as though the structure member were declared as an output variable of the same type. Location layout qualifiers may be used on output variables declared as structures, but not on individual members. Location layout qualifiers may not be used on output blocks or output block members. The number of output locations available to a shader is limited. For fragment shaders, the limit is the advertised number of draw buffers. For all other shaders, the limit is implementation-dependent and must be no less than one fourth of the advertised maximum output component count. A program will fail to link if any attached shader uses a location greater than or equal to the number of supported locations, unless device-dependent optimizations are able to make the program fit within available hardware resources. A program will fail to link if any two fragment shader output variables are assigned to the same location and index, or if any two output variables from the same non-fragment shader stage are assigned to the same location. For fragment shader outputs, locations can be assigned using either a layout qualifier or via the OpenGL API. For all shader types, a program will fail to link if explicit location assignments leave the linker unable to find space for other variables without explicit assignments. For the purposes of determining if a non-fragment output matches an input from a subsequent shader stage, the location layout qualifier (if any) must match. -- Section 4.5.2, "Precision Qualifiers" (page 53) (add new paragraph to the end of the section) For the purposes of determining if an output from one shader stage matches an input of the next stage, the precision qualifier need not match. -- Section 4.6.1, "The Invariant Qualifier" (page 55) (add new paragraph to the end of the section) For the purposes of determining if an output from one shader stage matches an input of the next stage, the "invariant" qualifier need not match. -- Section 4.7, "The Precise Qualifier" (page 56) (add new paragraph to the end of the section) For the purposes of determining if an output from one shader stage matches an input of the next stage, the "precise" qualifier need not match. GLX Protocol The following rendering command is sent to the server as part of a glXRender request: UseProgramStages 2 8 rendering command length 2 ZZZZ rendering command opcode 4 ENUM type 4 CARD32 program ActiveShaderProgram 2 4 rendering command length 2 ZZZZ rendering command opcode 4 CARD32 program Errors UseProgramStages generates INVALID_OPERATION if the program parameter has not been successfully linked. UseProgramStages generates INVALID_OPERATION if transform feedback is active. UseProgramStages generates INVALID_VALUE if has a bit set for any other than TESS_CONTROL_SHADER_BIT, TESS_EVALUATION_- SHADER_BIT, VERTEX_SHADER_BIT, GEOMETRY_SHADER_BIT, or FRAGMENT_- SHADER_BIT, unless is ALL_SHADER_BITS. ActiveShaderProgram generates INVALID_OPERATION if the program parameter has not been successfully linked. The INVALID_OPERATION error produced by LinkProgram if the program object has a geometry, tessellation control, or tessellation evalutations shader attached and no vertex shader attached is now produced at Begin time. The error INVALID_OPERATION is generated if Begin, or any command that implicitly calls Begin, is called when a program object with multiple attached shaders is active for one or more, but not all of the shader program types corresponding to the shaders that are attached. The error INVALID_OPERATION is generated if Begin, or any command that implicitly calls Begin, is called when an active program object has two shaders attached that have shader program types in between them with active programs that are not zero and are not equal to the active program of the first two shaders. INVALID_OPERATION is generated if any of the commands added by this extension are executed between the execution of Begin and the corresponding execution of End. Dependencies on OpenGL 4.0 (Core Profile) If the OpenGL 4.0 core profile is used, references to built-in shader variables found only in the compatibility profile should be removed. Additionally, the fragment shader built-in input block "gl_PerFragment" doesn't exist, and references to it should be removed. When matching shader outputs to fragment inputs, the members of "gl_PerVertex" output block do not affect matching. References to fixed-function vertex and fragment processing should also be removed. Dependencies on GLSL 1.40 and earlier This extension typically requires that shaders redeclare "gl_PerVertex" or "gl_PerFragment" to use members of built-in input or output blocks in separable shaders. However, since input and output interface blocks are not supported in GLSL 1.40 or earlier, such redeclarations are not even possible using older versions of GLSL. To deal with this case, this extension provides a specific exception to this rule, allowing vertex and fragment shaders using #version 140 or lower to redeclare all variables that would otherwise belong to these blocks at global scope. When linking separable programs using such shaders, the set of redeclared inputs/outputs are taken to form an implicit redeclaration of "gl_PerVertex" or "gl_PerFragment". After this, normal matching rules for the gl_PerVertex and gl_PerFragment blocks are applied. When using this capability: * all built-in vertex outputs or fragment inputs must be redeclared; * all shaders of a given type must make the same redeclarations; and * to get an exact interface match, the vertex output and fragment input redeclarations must be compatible according to block matching rules. This exception is important because we expect this extension to be supported on implementations and GPUs supporting only OpenGL 2.1, which doesn't support the interface blocks added by GLSL 1.50. Note that this exception applies only to shaders using #version 140. When using this extension with shaders using #version 150 or higher, the shaders must redeclare gl_PerVertex or gl_PerFragment blocks. The following edits to the GLSL 1.40 (revision 7) specification are made when this extension is enabled by an #extension directive: Add new Section 7.7, Built-In Redeclaration and Separable Programs The following vertex shader outputs may be redeclared at global scope to specify a built-in output interface, with or without special qualifiers: gl_Position gl_PointSize gl_ClipDistance[] gl_ClipVertex (compatibility only) gl_FrontColor (compatibility only) gl_BackColor (compatibility only) gl_FrontSecondaryColor (compatibility only) gl_BackSecondaryColor (compatibility only) gl_TexCoord[] (compatibility only) gl_FogFragCoord (compatibility only) The following fragment shader inputs may be redeclared at global scope to specify a built-in input interface, with or without special qualifiers: gl_Color (compatibility only) gl_SecondaryColor (compatibility only) gl_TexCoord[] (compatibility only) gl_FogFragCoord (compatibility only) When compiling shaders using any of the above variables, all such variables must be redeclared prior to use. ((Note: This restriction applies only to shaders using version 140 or earlier that enable the ARB_separate_shader objects extension; shaders not enabling the extension do not have this requirement.)) A separable program object will fail to link if any attached shader uses one of the above variables without redeclaration, or if it has two shaders of the same type using any of these variables where the sets of variable declarations don't match exactly. Additionally, the API specification language in this specification (written assuming input and output blocks in GLSL) is modified as follows: (Add to the end of the "Shader Interface Matching" section) When using vertex or fragment shaders with version 140 or lower in separable programs, the language doesn't support input and output blocks or redeclaration of gl_PerVertex or gl_PerFragment. In such cases, an implicit block redeclaration is formed from the set of vertex shader outputs or fragment shader inputs redeclared according to Section 7.7 of the OpenGL Shading Language Specification. The order of individual variable redeclarations does not affect the resulting implicit block redeclaration. The block matching rules described above are then applied to such implicit block redeclarations. Note that an implicit block redeclaration is never considered to match with an explicit block redeclaration. Dependencies on ARB_geometry_shader4, EXT_geometry_shader4, NV_geometry_- shader4, and/or OpenGL version 3.2 If none of ARB_geometry_shader4, EXT_geometry_shader4, NV_geometry_- shader4, or OpenGL 3.2 are supported by the implementation, ignore all references to geometry shaders and generate an INVALID_ENUM error when UseProgramStages is called with GEOMETRY_SHADER_BIT set in . Dependencies on ARB_tessellation_shader and OpenGL 4.0 If ARB_tessellation_shader and OpenGL 4.0 are not supported by the implementation, ignore references to tessellation control and evaluation shaders and generate an INVALID_ENUM error when UseProgramStages is called with TESS_CONTROL_SHADER_BIT or TESS_EVALUTAION_SHADER_BIT is set in . Dependencies on ARB_gpu_shader_fp64 and OpenGL 4.0 If ARB_gpu_shader_fp64 and OpenGL 4.0 are not supported by the implementation, ignore references to double sized uniforms including ProgramUniform* calls with a 'd' suffix. Additionally, references to double-precision GLSL variable types should be removed. Dependencies on ARB_explicit_attrib_location, ARB_vertex_attrib_64bit, OpenGL 3.3, and OpenGL 4.1 If ARB_explicit_attrib_location (or OpenGL 3.3) is supported, vertex shader input variables (including ones with double-precision components) can select associated generic attributes with an explicit location layout qualifier in lieu of calling BindAttribLocation. If ARB_vertex_attrib_64bit (or OpenGL 4.1) is supported, vertex shader inputs can use types with double-precision components. When these extensions are supported, there are special rules for the number of locations consumed by "dvec3" and "dvec4" types, which require more storage than is available in a four-component single-precision vector. The rules are: * dvec3/dvec4 vertex inputs consume one location (generic vertex attribute), but can count as two vectors for the purposes of determining if the vertex shader consumes too many inputs * dvec3/dvec4 inputs and outputs for other stages consume two locations The relevant spec edits (modifying language introduced by ARB_explicit_attrib_location) can be found in this extension. Dependencies on EXT_separate_shader_objects This extension provides program pipeline objects, to which separable program objects can be attached via UseProgramStages (for rendering) and ActiveShaderProgram (for uniform updates). A single pipeline object can be bound via BindProgramPipeline. The programs attached to the bound pipeline object are used unless a non-separable object is made current via UseProgram. Effectively UseProgram has a higher priority than BindProgramPipeline. EXT_separate_shader_objects does something very similar, but without pipeline objects. Instead, the single program attachment point set by UseProgram is replaced by an array of attachment points updated by UseShaderProgramEXT and ActiveProgramEXT. UseProgram is redefined to update all attachment points. This collection of attachment points is functionally equivalent to the program pipeline object in this extension, and can be thought of as a special pipeline object. If both extensions are supported, the rule giving priority to UseProgram over pipeline objects needs to be updated, given that the single UseProgram binding point is replaced by a collection of binding points. We effectively treat this collection of binding points as another pipeline object, and treat that object as higher priority if it has a program attached to *any* attachment point. The priority rules in this spec are rewritten as follows: The executable code for an individual shader stage is taken from the current program for that stage. If there is a current program object for any shader stage or for uniform updates established by UseProgram, UseShaderProgramEXT, or ActiveProgramEXT, the current program for that stage (if any) is considered current. Otherwise, if there is a bound program pipeline object ... Note that with these rules, it's not possible to mix program objects bound to the context with program objects bound to a program pipeline object; if any program is bound to the context, the current pipeline object is ignored. Dependencies on ARB_vertex_program, ARB_fragment_program, NV_gpu_program4, and related assembly extensions On implementations supporting both GLSL and assembly programmability, it is necessary to make a determination of what executable code (if any) is run in each program stage. The logic for determining the active executable is as follows: * If there is an active GLSL program for the stage, either from a program bound by UseProgram or from a program bound to the active program pipeline object, that program's executable will be used. * Otherwise, the bound assembly program from this stage will be used if enabled. * Otherwise, the stage will be skipped (tessellation control, evaluation, and geometry), fixed function vertex or fragment processing will be used (compatibility profile), or undefined results will occur (core profile). This is the same behavior present without this extension; the only difference is that active GLSL programs are determined on a stage-by-stage basis with this extension. New State Add to Table 6.45 (Program Object State): Get Value Type Get Command Initial Value Description Sec Attribute ------------------- ---- -------------------- ------------- ------------------------ ------ --------- ACTIVE_PROGRAM Z+ GetProgramPipelineiv 0 The program object 2.20.2 - that Uniform* commands update when PPO bound VERTEX_SHADER Z+ GetProgramPipelineiv 0 Name of current vertex 2.20.2 - shader program object GEOMETRY_SHADER Z+ GetProgramPipelineiv 0 Name of current geometry 2.20.2 - shader program object FRAGMENT_SHADER Z+ GetProgramPipelineiv 0 Name of current fragment 2.20.2 - shader program object TESS_CONTROL_SHADER Z+ GetProgramPipelineiv 0 Name of current tessell- 2.20.2 - ation control shader program object TESS_EVALUATION_SHADER Z+ GetProgramPipelineiv 0 Name of current tessell- 2.20.2 - ation evaluation shader program object VALIDATE_STATUS B GetProgramPipelineiv FALSE Validate status of 2.14.8 - program pipeline object PROGRAM_PIPELINE_- Z+ GetIntegerv 0 Current program pipeline 2.14.PPO - BINDING object binding New Implementation Dependent State None Issues 1. What should this extension be called? RESOLVED: ARB_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). The ability to use monolithic program objects that might be more optimized with individual shader program objects makes this name a little less appropriate. 1a. How is the extension different from the prior EXT version? RESOLVED: The ARB extension is a strict superset adding: * tessellation interactions, and * GLSL language additions for layout qualifiers to support rendezous-by-API-resource and rendezous-by-structure-offset cross-stage interfacing. * A container program pipeline object to bind separate programs to rather than to the context directly. * Support for transform feedback interactions. * CreateShaderProgramv takes multiple strings to better match ShaderSource * More. . . 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: In a program pipeline object, this extension provides separate program binding points for each stage, as well as an "active" program specified by glActiveShaderProgram. When glUniform is called when a program pipeline object is active, the active program specifies the program 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 glGetProgramPipelineiv with a of GL_ACTIVE_PROGRAM. When a non-zero program is passed to UseProgram, any subsequent uniform updates will affect that program, ignoring the active program in any bound pipeline object. For example: glUseProgram(0); glBindProgramPipeline(1); glActiveProgram(1, 2); glUniform1f(0, 3.0); // affects program 2 glUseProgram(3); glUniform1f(0, 3.0); // affects program 3 glUseProgram(0); glUniform1f(0, 3.0); // affects program 2 As an alternative to setting the GL_ACTIVE_PROGRAM selector with glActiveShaderProgram, 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)? RESOLVED: No, the glGetUniform* queries take the program object for the query as an explicit parameter to the query. These queries do not rely on a selector. In other words, the uniform queries are always selector-free. 6a. Should the fragment shader program object be allowed to changed within transform feedback mode? RESOLVED: No, this should generate a 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, glUseProgramStages 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 happens if you have a program object current for a shader stage, but the program object doesn't contain an executable for that stage? RESOLVED: This is not an error; instead it is as though there were no program bound to that stage. We have two different notions for programs bound to shader stages. A program is "current" for a stage if it bound to that stage in the active program pipeline object. A program is "active" for a stage if it is current and it has an executable for this stage. In this case, the program would be current but not active. When no program is active for a stage, the stage will be replaced with fixed functionality logic (compatibility profile vertex and fragment), disabled (tessellation control and evaluation, geometry), or have undefined results (core profile vertex and fragment). Support for programs that are current but not active is intentional behavior. Consider an example where an application wants to use two different types of separate program object -- one for all types of vertex processing and a second for fragment processing. Some of the vertex pipe programs might include tessellation or geometry shaders; others might only include a vertex shader. With this configuration, the application can use code like the following: #define GL_ALL_VERTEX_PIPE_SHADER_BITS \ (GL_VERTEX_SHADER_BIT | \ GL_TESS_CONTROL_SHADER_BIT | \ GL_TESS_EVALUATION_SHADER_BIT | \ GL_GEOMETRY_SHADER_BIT) glUseProgramStages(pipeline, GL_ALL_VERTEX_PIPE_SHADER_BITS, vertex_pipe_program); glUseProgramStages(pipeline, GL_FRAGMENT_SHADER_BIT, fragment_pipe_program); Such code wouldn't have to determine if has tessellation or geometry shaders. Instead, it simply sets all possible bits, which removes the old program from all non-fragment stages. For stages not present in the new program, the program will be current but not active, and it will be as though no program were bound to such stages. 8a. What happens if a linked program object with multiple stages (e.g., vertex and fragment) is active on those stages, but there is a second program active in stages between the first and last stages of that program (e.g., a geometry-only program)? RESOLVED: Such a configuration will result in a draw-time validation error. We allow the linker to perform internal optimizations on the interfaces between stages of a multi-stage program object. For a vertex-fragment program, the vertex shader outputs can be optimized to pass along only those outputs needed as fragment shader inputs. Such a shader would not necessarily be set up to successfully pass those outputs to a separate geometry-only program, even if the declared vertex outputs would naturally match up with the declared geometry inputs. 8b. What happens if a linked program object with multiple stages is active on some of its stages, but not on others? RESOLVED: Such a configuration would result in a draw-time validation error. Consider a program with vertex and fragment shaders, where the interface between stages is optimized as in the previous example. If the vertex shader from this program were to be used with a separate fragment-only program instead of the program's fragment shader, the optimized vertex outputs wouldn't necessarily match the inputs from the second program, even if the set of variables on that interface were compatible. 9. Is glUseProgramStages 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 glCreateShaderProgram 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-stage linking. These features are not particularly relevant for creating separate shader programs. 11. Can glCreateShaderProgram be compiled into a display list? RESOLVED: No. glCreateShaderProgram is equivalent to a sequence of commands that are themselves not allowed to be compiled into a display list. 12. Should glCreateShaderProgram allow user-defined varyings? RESOLVED: Yes. However, to get defined results when passing varying values between separate programs, applications are required to match inputs to outputs. This matching can be achieved either with the "location" layout qualifier, or by declaring the exact same set of inputs and outputs in the adjacent shader stages. 13. How are interpolation modifiers handled for separate shader programs? RESOLVED: GLSL only provides interpolation modifiers for user- defined varyings. These modifiers can be used in conjunction with the layout location qualifiers specified in this extension. Such modifiers must match. 14. Should glLinkProgram work to re-link a shader created with glCreateShaderProgram? RESOLVED: NO because the shader created by glCreateShaderProgram is detached and deleted as part of the glCreateShaderProgram 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 glCreateShaderProgram is used because the shader object is detached and deleted. User-defined attributes will work when glCreateShaderProgram is used to easily create a vertex shader program, but the application 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 glCreateShaderProgram 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. GLuint ppo; GenProgramPipelines(1, &ppo); BindProgramPipeline(ppo); 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 glCreateShaderProgram 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 glUseProgramStages(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 glCreateShaderProgram 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 glCreateShaderProgram, 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: GLuint ppo; GenProgramPipelines(1, &ppo); BindProgramPipeline(ppo); 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 glCreateShaderProgram 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 glUseProgramStages(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 in transform feedback from a separate shader program created with glCreateShaderProgram? RESOLVED: No. glTransformFeedbackVaryings requires a re-link to take effect on a program. glCreateShaderProgram 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 a 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. Which should take precedence if both are bound, program objects or program pipeline objects? RESOLVED: Program objects. Due to concerns about existing middleware depending on the program object state to determine the current program rendering state, the program object should override any program pipeline object that might be bound. 20. Should UseProgramStages take a bitfield rather than derive the information from the program object? RESOLVED: Yes. Though it seems pointless to include a bitfield that can only be erroneous if it includes bits set for shaders not present in the program object, without it there is no way to disassociate a shader type from a program object once it has been done. 21. What should the behavior be if a program object is deleted that is part of the current program pipeline object? RESOLVED: Just as program objects made current via UseProgram are flagged for deletion until they are no longer referenced, program objects that form part of the current program pipeline object will be flagged and remain until no references remain. Deletion of current program objects has special treatment in OpenGL. Such are not immediately deleted, but rather flagged for deletion and remain until they are no longer referenced. Being current indirectly as part of the current program pipeline object rather than directly via UseProgram makes no fundamental difference to the state of the program object or the rendering state. Whenever possible, an object made current as part of a container object should behave exactly as it would if it were to bypass that container object. In defference to that goal, objections to perpetuating the irregular behavior of program object deletion are set aside in favor of maintaining consistent behavior. 22. If multiple potential sources of transform feedback input are active from different program objects, where should transform feedback capture its input? RESOLVED: The later stage in the ordered pipeline of stages should be the source of the transform feedback input. This is true at any given time regardless of how the state may change due to binding and releasing of different program objects. So if a geometry shader program is active and then removed, transform feedback input may switch to the vertex shader. This potential for changes requires an error with ResumeTransformFeedback if the related state has changed since it was paused. 23. How do built-in inputs in one stage interface with built-in outputs from a previous stage? UNRESOLVED: There are several different classes of inputs that have different behavior: (a) "System inputs" are ones that are not derived directly from a corresponding output. These inputs are treated as though they had their own dedicated locations; use of these variables in a shader do not affect whether the shader matches up with the outputs of a previous shader stage. Examples of such inputs include "gl_InvocationID", "gl_SamplePosition", "gl_PointCoord", and "gl_TessCoord". (b) "System outputs" are are typically consumed by a fixed-function unit. These outputs are treated as though they had their own dedicated locations; use of these variables in a shader do not affect whether the shader matches up with the outputs of a previous shader stage. Examples of such outputs include "gl_Layer", "gl_TessLevelOuter[]". (c) Non-system inputs and outputs are those passed more-or-less directly between shader stages. For fragment shader inputs, non-system inputs may be interpolated, but the interpolated values will be derived directly from outputs of the previous shader stages. These inputs and outputs are not treated as having dedicated locations. To ensure an exact match between two shader stages, the set of non-system inputs and outputs on the interface must match. All built-in inputs and outputs not found in the gl_PerVertex and gl_PerFragment blocks are treated as belonging to categories (a) and (b). Members of gl_PerVertex may or may not be treated as "system" variables, depending on the specific interface. (See the next issue for more details.) 24. How does the use of built-in inputs or outputs affect the exact interface matching? Does their use affect matching for user-defined inputs? UNRESOLVED: As noted in the previous issue, built-ins outside the gl_PerVertex and gl_PerFragment blocks are considered "system" variables that don't affect interface matching at all. For members of gl_PerVertex and gl_PerFragment, there are two types of interface between separable programs with different rules. In interfaces not involving a fragment shader (e.g., vertex to geometry), shader outputs in gl_PerVertex are not interpreted by any fixed-function unit. As such, we will treat all inputs and outputs as non-system. To get defined results passing these built-ins between stages, gl_PerVertex must be declared identically on both sides of the interface. In interfaces involving a fragment shader, some of the gl_PerVertex outputs will be consumed by the rasterizer and may not be passed to subsequent stages. In particular, the built-in outputs gl_Position, gl_PointSize, gl_ClipDistance[], and gl_ClipVertex (compatibility only) are consumed by the rasterizer. gl_ClipDistance[] is available in the fragment shader, but will typically not be read there; all other outputs are not available in the fragment shader. As a result, these outputs are treated as system outputs and are ignored when testing if gl_PerVertex and gl_PerFragment match. Since gl_PerVertex and gl_PerFragment typically won't match, we specify a member-by-member comparison. A mismatch occurs if a gl_PerFragment input is found without a corresponding gl_PerVertex output, or vice versa. If non-system built-in inputs and outputs don't match on an interface, we don't guarantee that correct values are passed between stages (inputs are undefined). Additionally, a mismatch will mean that the values passed using user-defined inputs and outputs without location qualifiers are also not guaranteed, since the locations assigned for these built-ins might affect the assignments for user-defined variables. 25. How does the use of two-sided color built-ins (e.g., gl_FrontColor vs. gl_BackColor) affect the matching of inputs and outputs on an interface? UNRESOLVED: For interfaces between two non-fragment stages, front and back colors are treated as separate variables over the interfaces. For interfaces involving a non-fragment stage with fragment, both pairs of front and back colors are treated as a single color for matching purposes. For example, a vertex shader is treated as effectively writing the fragment input "gl_Color" if it writes either "gl_FrontColor" or "gl_BackColor". 26. How should built-in inputs behave when used with user-defined variables with explicit locations? UNRESOLVED: Built-ins are unaffected by the presence of user-defined variables with explicit locations. A mismatch in built-ins does not affect matching of user-defined variables with explicit locations. Note that built-ins can not be assigned explicit locations. This means that: (a) when non-system built-in usage doesn't match, the mismatch affects all such built-ins, plus any user-defined variables that aren't assigned explicit locations; and (b) when user-defined variables without locations don't match between shaders, the mismatch affects all non-system built-ins as well. 27. How does the handling of built-in inputs and outputs in this extension differ from EXT_separate_shader_objects? UNRESOLVED: In EXT_separate_shader_objects, shaders could only use built-ins to pass values between stages. In this extension, user-defined variables can be used. In this extension, the usage of "non-system" built-ins is required to match between stages. In EXT_separate_shader_objects, there was no requirement that the set of built-in outputs written by one stage had to match the inputs read by another stage. Implementations supporting EXT_separate_shader_objects are likely to provide logically separate locations for all shader built-ins. That extension didn't provide for undefined values when the set of built-ins used on one side of the interface didn't exactly match those on that other side, so implementations were required to assign matching locations even if texture coordinates or colors were used as outputs in one program but not inputs in another. 28. This extension requires shaders to redeclare gl_PerVertex and gl_PerFragment to use certain important built-ins. However, GLSL 1.40 (OpenGL 3.1 and earlier) doesn't support input and output blocks at all. Should we support this extension on such GL/GLSL versions? If so, how? RESOLVED: Yes, we expect that some implementations will want to support this extension on GPUs not capable of supporting OpenGL 3.2 and GLSL 1.50. To handle such cases, we don't require block redeclarations in shaders using #version 140 and earlier. Instead, we treat it these cases as though gl_PerVertex and gl_PerFragment existed and were re-declared implicitly. We allow shaders to redeclare all relevant built-ins, and require that shaders redeclare each of these built-ins that it uses. The set of redeclared built-ins is then assembled into an implicit block redeclaration and normal block matching rules are then applied. This capability is provided only for shaders using #version 140 or lower. We considered adding a forward compatibility path allowing similar constructs in #version 150 and higher shaders, but opted against adding a second mechanism where block redeclaration is already available. Additionally, the fact that #version 140 shaders using this feature already have to redeclare all relevant variables means that shaders written for #version 140 plus this extension are likely to already have something looking very much like a block redeclaration, and should be easily ported. We considered adding support for input and output blocks to GLSL 1.40 as part of this extension, but decided that was too large of a change. The relevant language here is only included in the extension spec. It doesn't need to be included in the core, because the only way to use the new features here with #version 140 shaders is via this extension. 29. How do input and output "location" layout qualifiers behave with this extension and ARB_explicit_attrib_location? RESOLVED: ARB_explicit_attrib_location added "location" layout qualifiers for vertex shader inputs and fragment shader outputs to interface with fixed-function vertex pulling and blending hardware. This extension adds "location" qualifiers for all other shader inputs and outputs. To use these qualifiers, shaders must either enable the appropriate extension(s) using #extension or select a GLSL version incorporating the functionality using #version. In vertex and fragment shaders, it may be necessary to enable both extensions -- one for inputs and the other for outputs. A shader using location layout qualifiers without an appropriate #extension or #version directive will fail to compile. 30. Can program pipeline objects be shared between contexts? RESOLVED: No. Like framebuffer and vertex array objects (added by OpenGL 3.0), they are considered "container" objects to which other shareable objects can be attached. 31. How does one figure out how many locations are consumed by an input or output? RESOLVED: Basic scalar and single-precision vector types are considered to consume one (vector) location. Double-precision scalar and vector types consume either one or two locations, as discussed further below. An array with elements, each consuming locations, will consume * locations. Matrix types are treated as arrays of two to four column vectors. Locations are assigned in structure types by assigning consecutive locations member-by-member according to the member declaration order. 31. How many locations are consumed by shader inputs and outputs with double-precision types? RESOLVED: For inputs and outputs passed between shader stages, values of type "double" and "dvec2" consume a single location. Values of type "dvec3" and "dvec4" require more storage than a single-precision four-component vector, and thus consume two locations. For vertex shader inputs, each location is associated with a generic vertex attribute. Since each such attribute in the API can hold a full "dvec4" if specified with VertexAttribL* or VertexAttribLPointer, values of type "double", "dvec2", "dvec3", and "dvec4" consume only a single location (generic vertex attribute). However, for the purposes of determining if a vertex shader uses "too many" attribute vectors in LinkProgram, vertex shader inputs of types "dvec3" and "dvec4" can be counted as consuming two vector attributes. For example, if a vertex shader specifies: layout(location=4) in dvec4 attribs[4]; the values for the four elements of "attribs" will be taken from vertex attributes 4-7, though "attribs" may be counted as consuming eight vectors worth of attributes. Arrays or matrix types with double-precision components are treated as comprising 33. Are location layout qualifiers allowed on block declarations? On block member declarations? RESOLVED: Location layout qualifiers are not allowed on either block or block member declarations in this extension. One implication of this behavior is that in input/output interface between programs, the sets of declared inputs and outputs must match exactly, since interface blocks can not be matched by location. Future extensions may consider relaxing either or both restrictions. 34. Should we ever allow inputs and outputs to match if they are of different type? RESOLVED: The location system in this extension is expressed in units of four-component vectors. Because of this common numeric location, we allow outputs with a vector type to be fed to inputs with a scalar or smaller vector type as long as they have the same location and basic component type. For example, if a vertex shader includes: layout(location = 4) out vec4 vsout; and a fragment shader includes: layout(location = 4) in vec2 fsin; the two components of will be obtained by interpolating the x and y components of . The z and w components of will be ignored. We do not permit this behavior for double-precision vectors, because large types (dvec3, dvec4) consume two locations while smaller types (double, dvec2) consume only one. Allowing this behavior would be problematic for arrays. For example, in a vertex shader output declared as: layout(location = 4) out dvec4 vsout[2]; "vsout[1]" would be assigned locations 6 and 7, while in a fragment shader input declared as layout(location = 4) in dvec2 fsin[2]; "fsin[1]" would be assigned location 5. 35. What are the rules for determining if inputs and outputs match by qualification? RESOLVED: In order for an input in one shader stage to be considered to match an output in another, some of the qualifiers must match but others need not match. In particular: * The base storage qualifier ("in" and "out") across an interface will naturally not match -- one side uses "in", the other uses "out". * Auxilliary storage qualifiers ("centroid", "sample", and "patch") and interpolation qualifiers ("flat", "smooth", "noperspective") must match. * The location layout qualifier, if specified, must match. * Layout qualifiers specific to one shader type (e.g., "stream" for geometry shader outputs) need not match. * Precision qualifiers have no effect in OpenGL and need not match. * The qualifiers "invariant" and "precise" affect only how outputs are computed within a shader stage and need not match between stages. 36. How does the behavior of input/output interface matching differ between separable programs and non-separable programs? RESOLVED: The rules for matching individual variables or block members between stages are identical for separable and non-separable programs, with one exception -- matching variables of different type with the same location, as discussed in issue 34, applies only to separable programs. However, the ability to enforce matching requirements differs between program types. In non-separable programs, both sides of an interface are contained in the same linked program. In this case, if the linker detects a mismatch, it will generate a link error. For separable programs, the two sides of an interface may be in different programs, so the linker will be unable to detect a mismatch. In these cases, applications are responsible for ensuring matching inputs/outputs are used on either side of the interface. Input variables are undefined when mismatches occur. Matching can be done across the entire interface by ensuring that the exact same set of declarations is used on both sides of the interface. Alternately, matching can be done variable-by-variable by using identical types and matching location layout qualifiers. Revision History Rev. Date Author Changes ---- ----------- --------- --------------------------------------------- 25 1 Aug 2011 pbrown More clearly specify interface matching rules for shader inputs and outputs, for cases where both sides of an interface are found in the same program and where they are in different programs (bug 7030). Add dependencies with several ARB extensions and core version. Add several new spec issues related to shader interface matching. Add GLSL spec language describing what qualifiers must match for inputs/outputs to be considered to match in qualification. Add clarifications on the number of locations consumed by different types of shader inputs/outputs. Specify that vertex shader inputs of type "dvec3" and "dvec4" consume a single location for the purposes of matching with generic vertex attributes in the API (bug 7809). More clearly specify that location layout qualifiers are not allowed on blocks and block members. 24 25 Jul 2011 pbrown Remove the language erroneously deleting CURRENT_PROGRAM. In the EXT extension, this token was aliased to ACTIVE_PROGRAM_EXT, and was used to indicate the last program set by either ActiveProgramEXT or UseProgram. In the ARB extension, the SSO active programs are now program pipeline object state and CURRENT_PROGRAM should still be used to query the last program set by UseProgram (bug 7822). 23 25 Jul 2011 Jon Leech Add VALIDATE_STATUS to state tables and GetProgramPipelineiv description (bug 7748). 22 6 Jun 2011 pbrown Treat program pipeline objects as non-shared container objects, like framebuffer and vertex array objects (bug 7713). 21 9 Aug 2010 pbrown Expand ProgramUniform* function prototypes to individual entries for tools parsing extension specs. Add missing "*" characters for ProgramUniform*v functions. 20 15 Jul 2010 pbrown Proposed update to locations for vectors with double-precision components (bug 6635). 19 13 Jul 2010 pbrown Clarify issues 7 and 8. 18 13 Jul 2010 Jon Leech Clarify interactions of current program & pbrown object and current program pipeline object, and error conditions when a PPO with missing shader stages is current. Add language for the interaction of separate shader objects and per-stage subroutine uniforms (bug 6641). Specify behavior for successful and failed links of programs bound to PPOs (bug 6642). Add interactions for assembly program extensions and EXT_separate_shader_objects. Add missing code for CreateShaderProgramv treating such programs as separable. Update miscellaneous spec sections that don't account for per-stage active programs. 17 08 Jul 2010 pbrown Fix interface matching language in "Inputs" section of GLSL spec; modify API spec to allow type mismatches when using location qualifiers (e.g., passing a vec4 to a vec3). 16 08 Jul 2010 pbrown Restore error for linking a non-separable program without a vertex shader (bug 6517). Modify language describing the number of available locations (bug 6598). Add language disallowing aliasing of inputs and outputs except for previously allowed vertex shader input aliasing (bug 6599). Further work on block matching rules for built-in input and output blocks, including final rules for #version 140 shaders (bug 6636). Miscellaneous typo fixes. 15 07 Jul 2010 pbrown Minor typo corrections. Add specific language for the core profile, which won't have gl_PerFragment. Add issue on the use of location qualifiers and #extension; fix spec to match. 14 21 Jun 2010 pbrown Updated "Shader Interface Matching" section to include new rules for built-in inputs and outputs. Added more dependencies on the core profile and older versions of GLSL. Added several issues. 13 07 Jun 2010 groth Minor relinking clarification. New begin error 12 01 Jun 2010 groth More clarifications. Better introduction More consistency. 11 28 May 2010 groth Language clarifications and issue corrections 10 21 May 2010 groth move new xfb errors into pre-existing list cleaned up sundry issues further clarified deletion behavior various other non-controversial cleanups 9 20 May 2010 groth Add validateProgramPipeline/infolog clarify xfb interaction complete interface location allocation language. mention location limits. 8 19 May 2010 groth Finish responding to Pat's feedback. Reorganization for clarity. 7 15 May 2010 groth Respond to various feedback 6 10 May 2010 groth multiple shaders to CreateShaderProgram. Rename ActiveProgram, CreateShaderProgram Sundry corrections. 5 08 May 2010 groth remove default PPO. add active program definitively to PPO. add a few issues. fix nits. 4 06 May 2010 groth Clarify PPO role. Add language about implicit interfaces. 3 04 May 2010 groth Add container object. Add DSA uniform commands. 2 23 Apr 2010 groth Fill out sections explaining GLSL layout pragmas. Add tessellation awareness. Forbid certain use of monolithic and shader programs. 1 13 Jan 2010 mjk Initial revision