Name EXT_separate_shader_objects Name Strings GL_EXT_separate_shader_objects Contributors Contributors to ARB_separate_shader_objects and ARB_explicit_attrib_location desktop OpenGL extensions from which this extension borrows heavily Contact Benj Lipchak, Apple (lipchak 'at' apple.com) Status Complete NOTE: there is an unrelated OpenGL extension also named "GL_EXT_separate_shader_objects", found in the OpenGL extension registry at http://www.opengl.org/registry/ . These two extensions have similar purposes, but completely different interfaces. Version Date: November 08, 2013 Revision: 7 Number OpenGL ES Extension #101 Dependencies Requires OpenGL ES 2.0. Written based on the wording of the OpenGL ES 2.0.25 Full Specification (November 2, 2010). Written based on the wording of The OpenGL ES Shading Language 1.0.17 Specification (May 12, 2009). OpenGL ES 3.0 affects the definition of this extension. NV_non_square_matrices affects the definition of this extension. Overview This extension is a subset of ARB_separate_shader_objects appropriate for OpenGL ES, and also tacks on ARB_explicit_attrib_location functionality. Conventional GLSL requires multiple shader stages (vertex and fragment) 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, GPU hardware supports 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 application's 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, UseProgramStagesEXT is used. The VERTEX_SHADER_BIT_EXT and FRAGMENT_SHADER_BIT_EXT tokens refer to the conventional vertex and fragment stages, respectively. ActiveShaderProgramEXT specifies the program that Uniform* commands will update. While ActiveShaderProgramEXT provides a selector for setting and querying uniform values of a program object with the conventional Uniform* commands, the ProgramUniform* 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 input 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 also introduces a layout location qualifier to GLSL to pre- assign attribute and varying locations to shader variables. This allows applications to globally assign a particular semantic meaning, such as diffuse color or vertex normal, to a particular attribute and/or varying location without knowing how that variable will be named in any particular shader. New Procedures and Functions void UseProgramStagesEXT(uint pipeline, bitfield stages, uint program); void ActiveShaderProgramEXT(uint pipeline, uint program); uint CreateShaderProgramvEXT(enum type, sizei count, const char **strings); void BindProgramPipelineEXT(uint pipeline); void DeleteProgramPipelinesEXT(sizei n, const uint *pipelines); void GenProgramPipelinesEXT(sizei n, uint *pipelines); boolean IsProgramPipelineEXT(uint pipeline); void ProgramParameteriEXT(uint program, enum pname, int value); void GetProgramPipelineivEXT(uint pipeline, enum pname, int *params); void ProgramUniform1iEXT(uint program, int location, int x); void ProgramUniform2iEXT(uint program, int location, int x, int y); void ProgramUniform3iEXT(uint program, int location, int x, int y, int z); void ProgramUniform4iEXT(uint program, int location, int x, int y, int z, int w); void ProgramUniform1fEXT(uint program, int location, float x); void ProgramUniform2fEXT(uint program, int location, float x, float y); void ProgramUniform3fEXT(uint program, int location, float x, float y, float z); void ProgramUniform4fEXT(uint program, int location, float x, float y, float z, float w); void ProgramUniform1uiEXT(uint program, int location, uint x); void ProgramUniform2uiEXT(uint program, int location, uint x, uint y); void ProgramUniform3uiEXT(uint program, int location, uint x, uint y, uint z); void ProgramUniform4uiEXT(uint program, int location, uint x, uint y, uint z, uint w); void ProgramUniform1ivEXT(uint program, int location, sizei count, const int *value); void ProgramUniform2ivEXT(uint program, int location, sizei count, const int *value); void ProgramUniform3ivEXT(uint program, int location, sizei count, const int *value); void ProgramUniform4ivEXT(uint program, int location, sizei count, const int *value); void ProgramUniform1fvEXT(uint program, int location, sizei count, const float *value); void ProgramUniform2fvEXT(uint program, int location, sizei count, const float *value); void ProgramUniform3fvEXT(uint program, int location, sizei count, const float *value); void ProgramUniform4fvEXT(uint program, int location, sizei count, const float *value); void ProgramUniform1uivEXT(uint program, int location, sizei count, const uint *value); void ProgramUniform2uivEXT(uint program, int location, sizei count, const uint *value); void ProgramUniform3uivEXT(uint program, int location, sizei count, const uint *value); void ProgramUniform4uivEXT(uint program, int location, sizei count, const uint *value); void ProgramUniformMatrix2fvEXT(uint program, int location, sizei count, boolean transpose, const float *value); void ProgramUniformMatrix3fvEXT(uint program, int location, sizei count, boolean transpose, const float *value); void ProgramUniformMatrix4fvEXT(uint program, int location, sizei count, boolean transpose, const float *value); void ProgramUniformMatrix2x3fvEXT(uint program, int location, sizei count, boolean transpose, const float *value); void ProgramUniformMatrix3x2fvEXT(uint program, int location, sizei count, boolean transpose, const float *value); void ProgramUniformMatrix2x4fvEXT(uint program, int location, sizei count, boolean transpose, const float *value); void ProgramUniformMatrix4x2fvEXT(uint program, int location, sizei count, boolean transpose, const float *value); void ProgramUniformMatrix3x4fvEXT(uint program, int location, sizei count, boolean transpose, const float *value); void ProgramUniformMatrix4x3fvEXT(uint program, int location, sizei count, boolean transpose, const float *value); void ValidateProgramPipelineEXT(uint pipeline); void GetProgramPipelineInfoLogEXT(uint pipeline, sizei bufSize, sizei *length, char *infoLog); New Tokens Accepted by parameter to UseProgramStagesEXT: VERTEX_SHADER_BIT_EXT 0x00000001 FRAGMENT_SHADER_BIT_EXT 0x00000002 ALL_SHADER_BITS_EXT 0xFFFFFFFF Accepted by the parameter of ProgramParameteriEXT and GetProgramiv: PROGRAM_SEPARABLE_EXT 0x8258 Accepted by parameter to GetProgramPipelineivEXT: ACTIVE_PROGRAM_EXT 0x8259 Accepted by the parameter of GetBooleanv, GetIntegerv, and GetFloatv: PROGRAM_PIPELINE_BINDING_EXT 0x825A Additions to Chapter 2 of the OpenGL ES 2.0 Specification (OpenGL Operation): -- Section 2.10 "Vertex Shaders" (page 26) Modify the fourth and fifth paragraphs: "To use a vertex shader, shader source code is first loaded into a shader object and then compiled. Alternatively, pre-compiled shader binary code may be directly loaded into a shader object. An OpenGL ES implementation must support one of these methods for loading shaders. If the boolean value SHADER_COMPILER is TRUE, then the shader compiler is supported. If the integer value NUM_SHADER_BINARY_FORMATS is greater than zero, then shader binary loading is supported. A shader object corresponds to a stage in the rendering pipeline referred to as its shader stage or type. A vertex shader object is attached to a program object. The program object is then linked, which generates executable code from the compiled shader object(s) 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 sixth paragraph: "... A single program object can contain either a vertex shader, a fragment shader, or both." Modify the seventh 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, the results of vertex shader execution are undefined." -- Section 2.10.3 "Program Objects" (page 30) Modify the description of linking failures following the description of LinkProgram to read: "... if is not separable and does not contain both a vertex and a fragment shader, ..." Modify second paragraph, p. 31: "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 paragraph immediately after preceding paragraph: "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.10.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, the results of vertex and/or fragment processing will be undefined. However, this is not an error." Modify fourth and fifth paragraphs, p. 31: "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, UseProgramStagesEXT, or BindProgramPipelineEXT 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 UseProgramStagesEXT 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 UseProgramStagesEXT 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 BindProgramPipelineEXT." Insert prior to the description of DeleteProgram, p. 31: "Program parameters control aspects of how the program is linked, executed, or stored. To set a program parameter, call void ProgramParameteriEXT(uint program, enum pname, int value); identifies which parameter to set for program object . holds the value being set. If is PROGRAM_SEPARABLE_EXT, must be TRUE or FALSE and indicates whether the can be bound for individual pipeline stages via UseProgramStagesEXT after it is next linked." Modify the last paragraph of the section, p. 31: "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, is flagged ..." Insert at the end of the section, p. 31: "The command uint CreateShaderProgramvEXT(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. CreateShaderProgramvEXT 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); ProgramParameteriEXT(program, PROGRAM_SEPARABLE_EXT, 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 CreateShaderProgramvEXT 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." -- Add new section 2.10.PPO "Program Pipeline Objects" after 2.10.3 "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 GenProgramPipelinesEXT(sizei n, uint *pipelines); returns previously unused program pipeline object names in . These names are marked as used, for the purposes of GenProgramPipelinesEXT only, but they acquire state only when they are first bound. Program pipeline objects are deleted by calling void DeleteProgramPipelinesEXT(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 GenProgramPipelinesEXT with the command void BindProgramPipelineEXT(uint pipeline); is the program pipeline object name. The resulting program pipeline object is a new state vector, comprising all the state and with the same initial values listed in table 6.PPO. BindProgramPipelineEXT 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 BindProgramPipelineEXT 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.10.3. BindProgramPipelineEXT fails and an INVALID_OPERATION error is generated if is not zero or a name returned from a previous call to GenProgramPipelinesEXT, or if such a name has since been deleted with DeleteProgramPipelinesEXT. 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 UseProgramStagesEXT(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 vertex or fragment indicated by VERTEX_SHADER_BIT_EXT or FRAGMENT_SHADER_BIT_EXT respectively. The constant ALL_SHADER_BITS_EXT 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 UseProgramStagesEXT is called with set to zero or with a program object that contains no executable code for the 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_EXT 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_EXT 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 GenProgramPipelinesEXT, 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 BindProgramPipelineEXT creates a new program pipeline object. If is not a name returned from a previous call to GenProgramPipelinesEXT or if such a name has since been deleted by DeleteProgramPipelinesEXT, an INVALID_OPERATION error is generated. The command void ActiveShaderProgramEXT(uint pipeline, uint program); sets the linked program named by to be the active program (discussed later in the secion 2.10.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 GenProgramPipelinesEXT, 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 BindProgramPipelineEXT creates a new program pipeline object. If is not a name returned from a previous call to GenProgramPipelinesEXT or if such a name has since been deleted by DeleteProgramPipelinesEXT, an INVALID_OPERATION error is generated. Shader Interface Matching When linking a non-separable program object with multiple shader types, the outputs of one stage form an interface with the inputs of the next stage. These inputs and outputs must typically match in name, type, and qualification. When both sides of an interface are contained in the same program object, LinkProgram will detect mismatches on an interface and generate link errors. 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 inputs and outputs are considered to match exactly if and only if: * For every user-declared input variable declared, there is an output variable declared in the previous shader matching exactly in name, type, and qualification. * There are no user-defined output variables declared without a matching input 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.6.1 and 4.3.6.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 an output with the same location qualifier, data type, and qualification. Also, an input will be well-defined if the other program writes to an output matching the input in everything but data type as long as the output data type has the same basic component type and more components. The names of variables need not match when matching by location. For the purposes of interface matching, an input with a location qualifier is considered to match a corresponding output only if that output has an identical location qualifier. Built-in inputs or outputs 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: * Three unsigned integers (initially all zero) are required to hold each respective name of the current vertex stage program, current fragment 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.10.4 "Shader Variables" subsection "Vertex Attributes" Change the first sentence of the second full paragraph (p. 34): "When a program is linked, any active attributes without a binding specified either through BindAttribLocation or explicitly set within the shader text will be automatically bound to vertex attributes by the GL." Add the following sentence to the end of that same paragraph: "If an active attribute has a binding explicitly set within the shader text and a different binding assigned by BindAttribLocation, the assignment in the shader text is used." -- Section 2.10.4 "Shader Variables" subsection "Uniform Variables" Replace the paragraph introducing Uniform* (p. 37): "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 ActiveShaderProgramEXT is the active program object. If the current program pipeline object has no active program or there is no current program pipeline object, then there is no active program. The given values are loaded into the ... " Change the last bullet in the "Uniform Variables" subsection (p. 38) to: "* if there is no active program in use." Add to the end of the "Uniform Variables" subsection (p. 38): To load values into the uniform variables of a program which may not necessarily be bound, use the commands void ProgramUniform{1234}{if}EXT(uint program, int location, T value); void ProgramUniform{1234}uiEXT(uint program, int location, T value); void ProgramUniform{1234}{if}vEXT(uint program, int location, sizei count, const T *value); void ProgramUniform{1234}uivEXT(uint program, int location, sizei count, const uint *value); void ProgramUniformMatrix{234}fvEXT(uint program, int location, sizei count, boolean transpose, const float *value); void ProgramUniformMatrix{2x3,3x2,2x4, 4x2,3x4,4x3}fvEXT(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.10.5 "Shader Execution" (p. 40) Change the first paragraph: "If there is an active program object present for the vertex stage, the executable code for this active program is used to process incoming vertex values." Change first paragraph of subsection "Validation", p. 41: "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 (DrawArrays or DrawElements) 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" (p. 41): "* A program object is active for at least one, but not all of the shader stages that were present when the program was linked. * There is no 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 UseProgramStagesEXT with the PROGRAM_SEPARABLE_EXT 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 ValidateProgramPipelineEXT(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 GetProgramPipelineivEXT (See section 6.1.8). 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 GenProgramPipelinesEXT, 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 BindProgramPipelineEXT creates a new program pipeline object. If is not a name returned from a previous call to GenProgramPipelinesEXT or if such a name has since been deleted by DeleteProgramPipelinesEXT, an INVALID_OPERATION error is generated. Additions to Chapter 3 of the OpenGL ES 2.0 Specification (Rasterization) -- Section 3.8 "Fragment Shaders" (p. 86) Replace the last paragraph with: "When the program object currently in use for the fragment stage includes a fragment shader, its fragment shader is considered active and is used to process fragments. If the current fragment stage program object has no fragment shader or no program object is current for the fragment stage, the results of fragment shader execution are undefined." Additions to Chapter 4 of the OpenGL ES 2.0 Specification (Per-Fragment Operations and the Frame Buffer) None Additions to Chapter 5 of the OpenGL ES 2.0 Specification (Special Functions) None Additions to Chapter 6 of the OpenGL ES 2.0 Specification (State and State Requests) -- Section 6.1.8 "Shader and Program Queries" Add to GetProgramiv description: "If is PROGRAM_SEPARABLE_EXT, 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 UseProgramStagesEXT." Add after GetProgramiv description: "The command boolean IsProgramPipelineEXT(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, IsProgramPipelineEXT returns FALSE. No error is generated if is not a valid program pipeline object name. The command GetProgramPipelineivEXT(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 GenProgramPipelinesEXT, 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 BindProgramPipelineEXT creates a new program pipeline object. If is not a name returned from a previous call to GenProgramPipelinesEXT or if such a name has since been deleted by DeleteProgramPipelinesEXT, an INVALID_OPERATION error is generated. If is ACTIVE_PROGRAM_EXT, 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 VALIDATE_STATUS, the validation status of the program pipeline object, as determined by ValidateProgramPipelineEXT (see section 2.10.5) 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." 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 GetProgramPipelineInfoLogEXT(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 GetProgramPipelineivEXT 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 ES 2.0 Specification (Shared Objects and Multiple Contexts) (add sentence to third paragraph, p. 164) Program pipeline objects are not shared. Additions to the OpenGL ES Shading Language Specification, Version 1.0.17 Including the following line in a shader can be used to control the language feature described in thie extension: #extension GL_EXT_separate_shader_objects : where is as described in section 3.3. A new preprocessor #define is added to the OpenGL ES Shading Language: #define GL_EXT_separate_shader_objects 1 -- Section 4.3.3 "Attribute" (page 30): Add new section 4.3.3.1 "Attribute Layout Qualifiers" "Vertex shaders allow location layout qualifiers on attribute variable declarations. The location layout qualifier identifier for vertex shader attributes is: layout-qualifier-id location = integer-constant Only one argument is accepted. For example, layout(location = 3) attribute vec4 normal; establishes that the vertex shader attribute is copied in from vector location number 3. If an input variable with no location assigned in the shader text has a location specified through the OpenGL ES API, the API-assigned location will be used. Otherwise, such variables will be assigned a location by the linker. See section 2.10.4 of the OpenGL Specification for more details. A link error will occur if an attribute variable is declared in multiple vertex shaders with conflicting locations. -- Section 4.3.5 "Varying" (page 31): 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 vertex shader varying outputs and fragment shader varying inputs 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 varying layout qualifiers (Section 4.3.5.1) or by using identical varying declarations. Complete rules for interface matching are found in the "Shader Interface Matching" portion of section 2.10.PPO of the OpenGL Specification." Add new section 4.3.5.1 "Varying Layout Qualifiers" "All shaders allow location layout qualifiers on varying variable declarations. The location layout qualifier identifier for varyings is: layout-qualifier-id location = integer-constant Only one argument is accepted. For example, layout(location = 3) varying vec4 normal; establishes that the shader varying is assigned to vector location number 3. If the declared varying 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) varying vec4 colors[3]; will establish that the input is assigned to vector location numbers 6, 7, and 8. If the declared varying is an x 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) varying mat4 transforms[2]; will establish that varying 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. The number of varying locations available to a shader is limited to the implementation-dependent advertised maximum varying vector 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 varying variables are assigned to the same location, or if explicit location assignments leave the linker unable to find space for other variables without explicit assignments." Dependencies on OpenGL ES 3.0 If OpenGL ES 3.0 isn't present, references to ProgramUniform{1234}ui[v] should be ignored. Also, any redundant language about explicit shader variable locations set within the shader text should also be ignored. If neither OpenGL ES 3.0 nor NV_non_square_matrices is present, references to ProgramUniformMatrix{2x3,3x2,2x4,4x2,3x4,4x3}fv should be ignored. The behavior of mixing GLSL ES 1.00 shaders with GLSL ES 3.00 shaders in the same rendering pipeline is undefined. If the GL is OpenGL ES 3.0, make the following changes: Replace this sentence from the first paragraph of section 2.10.PPO Shader Interface Matching: "These inputs and outputs must typically match in name, type, and qualification." with the following language: "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." Add this paragraph after the first paragraph of section 2.10.PPO: "Variables declared as structures are considered to match in type if and only if structure members match in name, type, qualification, and declaration order. Variables 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 match in qualification are found in the OpenGL Shading Language Specification." Replace the last paragraph from section 2.10.PPO: "Built-in inputs or outputs 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." with the following new language: "When using GLSL ES 1.00 shaders, built-in inputs or outputs 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. When using GLSL ES 3.00 shaders in separable programs, gl_Position and gl_PointSize built-in outputs must be redeclared according to Section 7.5 of the OpenGL Shading Language Specification. Other built-in inputs or outputs 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." and add to GLSL ES 3.00 new section 7.5, 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 When compiling shaders using either of the above variables, both such variables must be redeclared prior to use. ((Note: This restriction applies only to shaders using version 300 that enable the EXT_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." Dependencies on NV_non_square_matrices If NV_non_square_matrices is supported, ProgramUniformMatrix{2x3,3x2,2x4,4x2,3x4,4x3}fvEXT is supported in OpenGL ES 2.0. Errors UseProgramStagesEXT generates INVALID_OPERATION if the program parameter has not been successfully linked. UseProgramStagesEXT generates INVALID_VALUE if has a bit set for any other than VERTEX_SHADER_BIT_EXT or FRAGMENT_SHADER_BIT_EXT, unless is ALL_SHADER_BITS_EXT. ActiveShaderProgramEXT generates INVALID_OPERATION if has not been successfully linked. DrawArrays and DrawElements generate INVALID_OPERATION 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. New State Add to table 6.15 (Program Object State): Initial Get Value Type Get Command Value Description Sec ------------------ ---- ----------------------- ------- ------------------------ ------ PROGRAM_PIPELINE_- Z+ GetIntegerv 0 Current program pipeline 2.10.PPO BINDING_EXT object binding Add new table 6.PPO (Program Pipeline Object State): Initial Get Value Type Get Command Value Description Sec ------------------ ---- ---------------------------- ------- ------------------------ ------ ACTIVE_PROGRAM_EXT Z+ GetProgramPipelineivEXT 0 The program object 2.10.PPO that Uniform* commands update when PPO bound VERTEX_SHADER Z+ GetProgramPipelineivEXT 0 Name of current vertex 2.10.PPO shader program object FRAGMENT_SHADER Z+ GetProgramPipelineivEXT 0 Name of current fragment 2.10.PPO shader program object VALIDATE_STATUS B GetProgramPipelineivEXT FALSE Validate status of 2.10.PPO program pipeline object S GetProgramPipelineInfoLogEXT empty Info log for program 6.1.8 pipeline object INFO_LOG_LENGTH Z+ GetProgramPipelineivEXT 0 Length of info log 6.1.8 New Implementation Dependent State None Issues See ARB_separate_shader_objects extension specification for issues documented while working on the original desktop OpenGL extension. Revision History Rev. Date Author Changes ---- ---------- --------- --------------------------------------------- 1 2011-06-17 Benj Initial revision for ES based on ARB_separate_shader_objects extension. 2 2011-07-22 Benj Rename APPLE to EXT, specify that PPOs are not shareable. 3 2011-07-26 Benj Add VALIDATE_STATUS to state tables and GetProgramPipelineivEXT description, remove the language erroneously deleting CURRENT_PROGRAM. 4 2013-03-07 Jon Leech Added note about the unrelated OpenGL extension of the same name. 5 2013-03-25 Benj Add interactions with OpenGL ES 3.0. 6 2013-09-20 dkoch Add interactions with NV_non_square_matrices. 7 2013-11-08 marka Clarify ProgramUniform*ui availability.