| Name |
| |
| EXT_separate_shader_objects |
| |
| Name Strings |
| |
| GL_EXT_separate_shader_objects |
| |
| Contact |
| |
| Mark Kilgard, NVIDIA (mjk 'at' nvidia.com) |
| |
| Contributors |
| |
| Pat Brown |
| Eric Werness |
| Robert Ohannessian |
| Jason Green, TransGaming |
| Kevin Rogovin |
| Greg Roth |
| |
| Status |
| |
| Shipping in NVIDIA 190.00 release drivers |
| |
| NOTE: there is an unrelated OpenGL ES extension also named |
| "GL_EXT_separate_shader_objects", found in the OpenGL ES extension |
| registry at http://www.khronos.org/registry/gles/ . These two extensions |
| have similar purposes, but completely different interfaces. |
| |
| Version |
| |
| Last Modified Date: March 7, 2013 |
| Version: 11 |
| |
| Number |
| |
| 377 |
| |
| Dependencies |
| |
| Written based on the wording of the OpenGL 3.0 (August 11, 2008) |
| specification. |
| |
| This extension requires OpenGL 2.0 or ARB_shader_objects. |
| |
| This extension depends on ARB_geometry_shader4, EXT_geometry_shader4, |
| and/or NV_geometry_shader4. |
| |
| Overview |
| |
| Prior to this extension, GLSL requires multiple shader domains |
| (vertex, fragment, geometry) to be linked into a single monolithic |
| program object to specify a GLSL shader for each domain. |
| |
| While GLSL's monolithic approach has some advantages for |
| optimizing shaders as a unit that span multiple domains, all |
| existing GPU hardware supports the more flexible mix-and-match |
| approach. |
| |
| HLSL9, Cg, the prior OpenGL assembly program extensions, and game |
| console programmers favor a more flexible "mix-and-match" approach to |
| specifying shaders independently for these different shader domains. |
| Many developers build their shader content around the mix-and-match |
| approach where they can use a single vertex shader with multiple |
| fragment shaders (or vice versa). |
| |
| This keep-it-simple extension adapts the "mix-and-match" shader |
| domain model for GLSL so different GLSL program objects can be bound |
| to different shader domains. |
| |
| This extension redefines the operation of glUseProgram(GLenum program) |
| to be equivalent to: |
| |
| glUseShaderProgramEXT(GL_VERTEX_SHADER, program); |
| glUseShaderProgramEXT(GL_GEOMETRY_SHADER_EXT, program); |
| glUseShaderProgramEXT(GL_FRAGMENT_SHADER, program); |
| glActiveProgramEXT(program); |
| |
| You can also call these commands separately to bind each respective |
| domain. The GL_VERTEX_SHADER, GL_GEOMETRY_SHADER_EXT, and |
| GL_FRAGMENT_SHADER tokens refer to the conventional vertex, geometry, |
| and fragment domains respectively. glActiveProgramEXT specifies |
| the program that glUniform* commands will update. |
| |
| Separate linking creates the possibility that certain output varyings |
| of a shader may go unread by the subsequent shader inputting varyings. |
| In this case, the output varyings are simply ignored. It is also |
| possible input varyings from a shader may not be written as output |
| varyings of a preceding shader. In this case, the unwritten input |
| varying values are undefined. Implementations are encouraged to |
| zero these undefined input varying values. |
| |
| This extension is a proof-of-concept that separate shader objects |
| can work for GLSL and a response to repeated requests for this |
| functionality. There are various loose ends, particularly when |
| dealing with user-defined varyings. The hope is a future extension |
| will improve this situation. |
| |
| New Procedures and Functions |
| |
| void UseShaderProgramEXT(enum type, uint program); |
| |
| void ActiveProgramEXT(uint program); |
| |
| uint CreateShaderProgramEXT(enum type, const char *string); |
| |
| New Tokens |
| |
| Accepted by <type> parameter to GetIntegerv and GetFloatv: |
| |
| ACTIVE_PROGRAM_EXT 0x8B8D (alias for CURRENT_PROGRAM) |
| |
| Additions to Chapter 2 of the OpenGL 3.0 Specification (OpenGL Operation) |
| |
| -- Section 2.20.2 "Program Objects" (page 91) |
| |
| Add this paragraph after the 6th paragraph: |
| |
| "The command |
| |
| uint CreateShaderProgramEXT(enum type, const char *sting); |
| |
| creates a stand-alone program from a source code string for a single |
| shader type. This command is equivalent to the following command |
| sequence: |
| |
| const uint shader = CreateShader(type); |
| if (shader) { |
| const int len = (int) strlen(string); |
| ShaderSource(shader, 1, &string, &len); |
| CompileShader(shader); |
| const uint program = CreateProgram(); |
| if (program) { |
| int compiled = FALSE; |
| GetShaderiv(shader, COMPILE_STATUS, &compiled); |
| if (compiled) { |
| AttachShader(program, shader); |
| LinkProgram(program); |
| DetachShader(program, shader); |
| } |
| |
| // Possibly... |
| if (active-user-defined-varyings-in-linked-program) { |
| append-error-to-info-log |
| set-program-link-status-false |
| } |
| |
| append-shader-info-log-to-program-info-log |
| } |
| DeleteShader(shader); |
| return program; |
| } else { |
| return 0; |
| } |
| |
| Notice the program may not actually link if the linked program would |
| contain active user-defined varyings (because such varyings would |
| not be well-defined for a single shader domain). If this situation |
| arises, the info log may explain this. |
| |
| Because no shader is returned by CreateShaderProgramEXT and the shader |
| that is created is deleted in the course of the command sequence, |
| the info log of the shader object is copied to the program so the |
| shader's failed info log for the failed compilation is accessible |
| to the application." |
| |
| Replace the 7th paragraph with: |
| |
| "If a valid executable is created, it can be made part of the current |
| rendering state with the command: |
| |
| void UseShaderProgramEXT(enum type, uint program); |
| |
| where type is one of VERTEX_SHADER, GEOMETRY_SHADER_ARB, or |
| FRAGMENT_SHADER program shader types, and program is the program |
| object program containing valid executable code, i.e. has been linked |
| successfully. Based on the type, the program becomes the current |
| vertex, fragment, or geometry shader program respectively and the |
| command installs the executable code as part of the respective current |
| rendering state. If UseShaderProgramEXT is called with program set |
| to zero, it is as if the GL has no respective (vertex, geometry, |
| or fragment) programmable stage configured and the corresponding |
| fixed-function path will be used instead. If program has not been |
| successfully linked, the error INVALID_OPERATION is generated and |
| the respective current shader state is not modified. |
| |
| The command |
| |
| void ActiveProgramEXT(uint program); |
| |
| sets the linked program named by program to be the active program |
| (discussed later in the "Uniform Variables" subsection of section |
| 2.20.3). If program has not been successfully linked, the error |
| INVALID_OPERATION is generated and active program is not modified. |
| |
| The command |
| |
| void UseProgram(uint program); |
| |
| is equivalent (modulo errors) to calling |
| |
| UseShaderProgramEXT(VERTEX_SHADER, program); |
| UseShaderProgramEXT(GEOMETRY_SHADER_EXT, program); |
| UseShaderProgramEXT(FRAGMENT_SHADER, program); |
| ActiveProgramEXT(program); |
| |
| If a program object contains multiple shader types but is not bound |
| for all its supported shader types, the program object's shader |
| types not bound do not affect GL's current rendering operation." |
| |
| -- Section 2.15.3 "Shader Variables" (page 97) |
| |
| Replace the 15th paragraph of the "Uniform Variables" section: |
| |
| "To load values into the uniform variables of the active program |
| object (specified by ActiveProgramEXT), use the commands ..." |
| |
| Change the last bullet in the "Uniform Variables" section to: |
| |
| "* if there is no active program in use." |
| |
| -- Section 2.20.4 "Shader Execution" (page 103) |
| |
| Change the first paragraph to read: |
| |
| "If a successfully linked program object that contains a vertex |
| shader is made current by calling UseShaderProgramEXT with a type of |
| VERTEX_SHADER, the executable version of the vertex shader is used to |
| process incoming vertex values rather than the fixed-function vertex |
| processing described in section 2.11 through 2.14. In particular, |
| ..." |
| |
| -- Section 2.20.5 "Required State" (page 109) |
| |
| Change the last paragraph to read: |
| |
| "Additionally, four unsigned integers (initially all zero) are |
| required to hold the each respective name of the current vertex |
| shader program, current geometry shader program, current fragment |
| shader program, and active program respectively." |
| |
| Additions to Chapter 3 of the OpenGL 3.0 Specification (Rasterization) |
| |
| -- Section 3.12 "Fragment Shaders" (page 231) |
| |
| Replace the second to the last paragraph with: |
| |
| "When the current fragment shader program object currently includes |
| a fragment shader, its fragment shader is considered active, and is |
| used to process fragments. If the fragment shader program object |
| has no fragment shader, or no fragment shader program object is |
| currently in use, the fixed-function fragment processing operations |
| described in the previous sections are used." |
| |
| -- Section 3.12.1 "Shader Variables" (page 232) |
| |
| Add this paragraph after the third paragraph: |
| |
| "User-defined varying values are well-defined only when the fragment |
| shader program object and the preceding programmable shading stage, |
| either the geometry shader stage if the geometry shader program |
| object contains geometry shader or else the vertex shader stage |
| if the vertex shader program object contains a vertex shader, are |
| the same program object. So user-defined varying values are only |
| well-defined when both the varying variable's output shader and |
| input shader are the same program object. |
| |
| In order to ensure well-defined behavior between a fragment shader |
| program with a different preceding geometry shader program or |
| vertex shader program when the current geometry shader program is |
| zero, applications must use the built-in varying variables such |
| as gl_TexCoord[0]. If the current fragment shader program object |
| uses user-defined input varying variables when the preceded current |
| geometry shader program is not the same program object or, in the |
| case the geometry shader program is zero, the preceding current |
| vertex shader program object is not the same program object, then |
| the values of such input varying variables are undefined. |
| |
| The state of user-defined varying inputs to a fragment shader |
| are undefined /even if/ the preceding shader has varying outputs |
| that match the same name and type of the subsequent shader. |
| Implementations are encouraged but not required to force these |
| undefined input varying variables to zero." |
| |
| Additions to Chapter 4 of the OpenGL 3.0 Specification (Per-Fragment |
| Operations and the Frame Buffer) |
| |
| None |
| |
| Additions to Chapter 5 of the OpenGL 3.0 Specification (Special |
| Functions) |
| |
| None |
| |
| Additions to Chapter 6 of the OpenGL 3.0 Specification (State and |
| State Requests) |
| |
| -- Section 5.4 "Display Lists" (page 311) |
| |
| Add "CreateShaderProgramEXT" to the "Program and shader objects" |
| list of commands that cannot be compiled into a display list but |
| are instead executed immediately. |
| |
| Additions to the AGL/GLX/WGL Specifications |
| |
| None |
| |
| Additions to the OpenGL Shading Language |
| |
| None |
| |
| Additions to the ARB_geometry_shader4 specification |
| |
| -- Section 2.16, Geometry Shaders |
| |
| Replace the 3rd and 4th paragraphs to read: |
| |
| "Geometry shaders are created as described in section 2.15.1 using a |
| type parameter of GEOMETRY_SHADER_ARB. They are attached to and used |
| in program objects as described in section 2.15.2. When a geometry |
| shader program object currently in use includes a geometry shader, |
| its geometry shader is considered active, and is used to process |
| primitives. If the geometry shader program object has no geometry |
| shader, or no program object is in use, this new primitive processing |
| pipeline stage is bypassed. |
| |
| A program object that includes a geometry shader without a vertex |
| shader must only use built-in input varying variables; otherwise |
| a link error may occur." |
| |
| -- Section 2.16.4, Geometry Shader Execution Environment |
| |
| Change the first paragraph to read: |
| |
| "If a successfully linked program object that contains a geometry shader is |
| made current as the geometry shader program object by calling |
| UseShaderProgramEXT with a type of GL_GEOMETRY_SHADER_ARB, the |
| executable version of the geometry shader is used to process |
| primitives resulting from the primitive assembly stage." |
| |
| Add these paragraphs to the end of the section: |
| |
| "User-defined varying values are well-defined only when the geometry |
| shader program object and the preceding vertex shader program object |
| are the same program object. So user-defined varying values are only |
| well-defined when both the varying variable's output shader and |
| input shader are the same program object. |
| |
| In order to ensure well-defined behavior between a geometry shader |
| program with a different preceding vertex shader program, applications |
| must use the built-in varying variables such as gl_TexCoord[0]. |
| If the current geometry shader program object uses user-defined |
| input varying variables when the preceded current vertex shader |
| program object is not the same program object, then the values of |
| such input varying variables are undefined. |
| |
| The state of user-defined varying inputs to a geometry shader |
| are undefined /even if/ the preceding vertex shader has varying |
| outputs that match the same name and type of the subsequent shader. |
| Implementations are encouraged but not required to force these |
| undefined input varying variables to zero." |
| |
| GLX Protocol |
| |
| UNDER DEVELOPMENT |
| |
| Errors |
| |
| UseShaderProgramEXT generates INVALID_ENUM if the type parameter is |
| not one of VERTEX_SHADER, GEOMETRY_SHADER_ARB, or FRAGMENT_SHADER. |
| |
| UseShaderProgramEXT generates INVALID_OPERATION if the program |
| parameter has not been successfully linked. |
| |
| UseShaderProgramEXT generates INVALID_OPERATION if transform feedback |
| is active. |
| |
| ActiveProgramEXT generates INVALID_OPERATION if the program parameter |
| has not been successfully linked. |
| |
| LinkProgram NO LONGER generates an INVALID_OPERATION if the program |
| object has a geometry shader attached and no vertex shader attached |
| as long as the geometry shader uses only built-in varying input |
| variables. |
| |
| Dependencies on ARB_geometry_shader4, EXT_geometry_shader4, and/or NV_geometry_shader4 |
| |
| If none of ARB_geometry_shader4, EXT_geometry_shader4, or |
| NV_geometry_shader4 are supported by the implementation, ignore all |
| references to geometry shaders and generate an INVALID_ENUM error |
| when UseShaderProgramEXT is called with the token GEOMETRY_SHADER_ARB. |
| |
| New State |
| |
| Remove CURRENT_PROGRAM from table 6.30 (Program Object State) and |
| append these rows: |
| |
| Get Value Type Get Command Initial Value Description Sec Attribute |
| ------------------- ---- ----------- ------------- ------------------------ ------ --------- |
| ACTIVE_PROGRAM_EXT Z+ GetIntegerv 0 The program object 2.20.2 - |
| (alias for that Uniform* commands |
| CURRENT_PROGRAM) update |
| VERTEX_SHADER Z+ GetIntegerv 0 Name of current vertex 2.20.2 - |
| shader program object |
| GEOMETRY_SHADER_ARB Z+ GetIntegerv 0 Name of current geometry 2.20.2 - |
| shader program object |
| FRAGMENT_SHADER Z+ GetIntegerv 0 Name of current fragment 2.20.2 - |
| shader program object |
| |
| New Implementation Dependent State |
| |
| None |
| |
| Issues |
| |
| 1. What should this extension be called? |
| |
| RESOLVED: EXT_separate_shader_objects |
| |
| The adjective "separate" is used in several extension names |
| (EXT_blend_equation_separate, EXT_blend_func_separate, |
| EXT_separate_specular_color, ATI_separate_stencil) when joined |
| state is made configurable separately. |
| |
| The phrase "shader_objects" refers generally to GLSL shader |
| objects, matching the ARB_shader_objects name. |
| |
| Whether the name should be "separate_shader_objects" |
| or "shader_objects_separate" is less clear. The various |
| "separate" extensions have different conventions as to whether |
| separate is prefixed or suffixed with the separated state. |
| The prefixed form is more natural to say aloud, is consistent |
| with the ATI_separate_stencil naming approach, and abbreviates |
| to SSO (instead of the inopportune abbreviation SOS). |
| |
| 2. What happens to a user-defined input varying variable that are |
| not written by a preceding shader's write to the corresponding |
| output varying variable. |
| |
| RESOLVED: The input variable variable's value is left undefined. |
| Implementations are encouraged but not required to zero the |
| value. |
| |
| GLSL has a "rendezvous by name" model for connecting varying |
| output variables to varying input variables of a subsequent |
| shader. With separate shaders, there's no assurance whether a |
| preceding shader will write a given user-defined input varying |
| variable. HLSL9, Cg, and OpenGL assembly extension programs |
| handle this situation by with "rendezvous by API resource" model. |
| In GLSL terms, this means separate GLSL shaders /must/ communicate |
| by built-in varying variables rather than user-defined varying |
| variables. |
| |
| It is undesirable from a performance standpoint to attempt to |
| support "rendezvous by name" for arbitrary separate shaders |
| because the separate shaders won't be naturally compiled to |
| match their varying inputs and outputs of the same name without |
| a special link step. Such a special link would introduce an |
| extra validation overhead to binding separate shaders. The link |
| itself would have to be deferred until glBegin time since separate |
| shaders won't match when transitioning from one set of consistent |
| shaders to another. This special link would still create errors |
| or undefined behavior when the names of input and output varyings |
| matched but their types did not match. |
| |
| Also the expectation from other shading APIs that support |
| mix-and-match shader usage is that "rendezvous by API resource" |
| is the expected norm. |
| |
| Specifying the behavior being undefined allows a future ARB |
| version of this extension to be more specific without encumbering |
| this extension with enforcing a specific error. |
| |
| 3. Do different program objects currently used by different shader |
| types share a single name space for uniforms? |
| |
| RESOLVED: No, different program objects have their own separate |
| name space for uniforms and each has locations specific to its |
| unique program object. |
| |
| 4. How do the glUniform* commands determine what program object |
| to query? |
| |
| RESOLVED: This extension introduces the active program specified |
| by glActiveProgramEXT (similar to the active texture selector |
| specified by glActiveTexture) to specify the selector used by |
| glUniform* commands. |
| |
| This active program is simply a selector and doesn't actually |
| control any rendering operation. |
| |
| The active program can be queried with glGetIntegerv with |
| the GL_ACTIVE_PROGRAM_EXT token which is an alias for |
| GL_CURRENT_PROGRAM. |
| |
| As an alternative to setting the GL_ACTIVE_PROGRAM_EXT selector |
| with glActiveProgramEXT, applications are instead encouraged |
| to use the glProgramUniform* commands introduced by the |
| EXT_direct_state_access extension which do not depend on a |
| selector but specify the program object with which to update |
| the specified uniform location explicitly. |
| |
| 5. Do the glGetUniform* queries depend on the active program state |
| (GL_ACTIVE_PROGRAM_EXT)? |
| |
| RESOLVED: No, the glGetUniform* queries take the program |
| object for the query as an explicit parameter to the query. |
| These commands do not rely on a selector. |
| |
| 6a. Should the fragment shader program object be allowed to changed |
| within transform feedback mode? |
| |
| RESOLVED: No, this should generate an GL_INVALID_OPERATION error. |
| |
| The OpenGL 3.0 and EXT_transform_feedback specifications say |
| glUseProgram generates a GL_INVALID_OPERATION error when transform |
| feedback is active. |
| |
| The rationale for this is that user-defined varying outputs from |
| the vertex or geometry shader might change. |
| |
| Perhaps it is desirable to allow different shader program objects |
| when transform feedback mode is active, but this extension |
| doesn't change the existing GLSL error behavior. In fact, |
| glUseShaderProgramEXT generate the same error glUseProgram does. |
| |
| 6b. Should the active program be allowed to changed within transform |
| feedback mode? |
| |
| RESOLVED: Yes. |
| |
| The active program simply allows uniforms to be changed but |
| doesn't actually change how the graphics pipeline itself is |
| configured or what programs are used for vertex, geometry, |
| and fragment processing. |
| |
| 7. What if a program object contains shaders from two domains, say |
| both a vertex shader and a geometry shader, and the program object |
| is just used as the current fragment shader program object? |
| |
| RESOLVED: The vertex shader within the program object is |
| simply ignored. |
| |
| 8. What if a program object contains both a vertex and fragment |
| shader and this program object is bound to both the current |
| vertex shader and fragment shader program object but there is |
| also a different geometry shader program object bound? |
| |
| RESOLVED: This works as long as the vertex shader and fragment |
| shader rely on built-in varying variables to communicate and don't |
| depend on passing values between each other with user-defined |
| varying variables because such variables are undefined if an |
| intervening different geometry shader program object is currently |
| used. Specifically, the vertex shader will output to its |
| built-in varying output variables and the different geometry |
| shader program object can read those built-in varying values |
| through input varying variables. Likewise the fragment shader |
| can use built-in varying input variables to get varying data |
| from the different geometry shader program object. |
| |
| 9. Is glUseShaderProgramEXT allowed to be compiled within a |
| display list? |
| |
| RESOLVED: Yes, just like glUseProgram is allowed within a |
| display list. |
| |
| 10. Should there be some easier to use API for creating a GLSL |
| program that programs a single shader type? |
| |
| RESOLVED: Yes, see the glCreateShaderProgramEXT command. |
| |
| The existing GLSL API for creating a GLSL program involves a lot |
| of steps to support multiple source strings, re-specification of |
| source code, attaching and detaching multiple shader objects, |
| and cross-domain linking. These features are not particularly |
| relevant for creating separate shader programs. |
| |
| 11. Can glCreateShaderProgramEXT be compiled into a display list? |
| |
| RESOLVED: No. |
| |
| glCreateShaderProgramEXT is equivalent to a sequence of commands |
| that are themselves not allowed to be compiled into a display |
| list. |
| |
| 12. Should glCreateShaderProgramEXT allow user-defined varyings? |
| |
| RESOLVED: User-defined varyings are permitted (without error) |
| but shouldn't be used because their behavior is not defined. |
| |
| glCreateShaderProgramEXT is likely to be used for compiling |
| separate shaders. The tenative resolution to issue 2 says the |
| values of user-defined varying input varaibles are undefined if |
| the preceding shader doesn't belong to the same program object. |
| Since the programs returned by glCreateShaderProgramEXT are |
| always for a single domain, there's no point allowing user-defined |
| varyings if they can't be assumed to be well-defined. |
| |
| 13. How are interpolation modifiers handled for separate shader |
| programs? |
| |
| RESOLVED: For now, interpolation modifiers aren't supported |
| for separate shader object varyings. |
| |
| Future resolution: Unfortunately GLSL only provides interpolation |
| modifiers for user-defined varyings which aren't well-defined |
| for separate shader programs. |
| |
| In the short-term, interpolation modifiers aren't commonly used |
| so not supporting interpolation modifiers for seperate GLSL |
| shader programs is probably acceptable. |
| |
| Long-term, GLSL can be extended with #pragma constructs that |
| specify to the compiler the interpolation modifier for a given |
| fragment shader built-in varying. Something like: |
| |
| #pragma interpolation(gl_TexCoord[0], centroid) |
| #pragma interpolation(gl_TexCoord[1], flat) |
| #pragma interpolation(gl_TexCoord[2], smooth) |
| #pragma interpolation(gl_TexCoord[3], invariant) |
| #pragma interpolation(gl_TexCoord[4], noperspective) |
| |
| This pragma is only legal within a fragment shader compilation |
| unit. The pragma can be specified multiple times, but |
| inconsistent specification of a specific built-in varying's |
| interpolation is not allowed. |
| |
| Alternatively, this extenion could add new built-in input varying |
| variables for the fragment shader: |
| |
| // TexCoord category |
| varying in centroid vec4 gl_CentroidTexCoord[]; |
| varying in centroid noperspective vec4 gl_CentroidNoPerspectiveTexCoord[]; |
| varying in float vec4 gl_FlatTexCoord[]; |
| varying in noperspective vec4 gl_NoPerspectiveTexCoord[]; |
| varying in ivec4 gl_IntTexCoord[]; |
| |
| // Color category |
| varying in centroid vec4 gl_CentroidColor; |
| |
| // Secondary color category |
| varying in centroid vec4 gl_CentroidSecondaryColor; |
| |
| // Fog category |
| varying in centroid vec4 gl_CentroidFogFragCoord; |
| |
| It would be an error to use a varying from more than one category |
| in a single program. |
| |
| 14. Should glLinkProgram work to re-link a shader created with |
| glCreateShaderProgramEXT? |
| |
| RESOLVED: NO because the shader created by glCreateShaderProgram |
| is detached and deleted as part of the glCreateShaderProgramEXT |
| sequence. This means if you call glLinkProgram on a program |
| returned from glCreateShaderProgram, you'll find the re-link |
| fails because no shader object is attached. |
| |
| An application is free to attach one or more new shader objects |
| to the program and then relink would work. |
| |
| This is fine because re-linking isn't necessary/expected. |
| |
| 15. Wouldn't re-linking be necessary if the application wanted to |
| use glBindAttribLocation to assign a user-defined attribute to |
| a specific vertex attribute? |
| |
| RESOLVED: Yes and that's a problem if glCreateShaderProgramEXT |
| is used because the shader object is detached and deleted. |
| |
| User-defined attributes will work when glCreateShaderProgramEXT |
| is used to easily create a vertex shader program, but the |
| appliation must be satisfied with the implementation-dependent |
| linker-assigned user-defined attributes returned by |
| glGetAttribLocation. |
| |
| We could provide a new set of built-in attributes that correspond |
| to declared as: |
| |
| attribute vec4 gl_VertexAttrib[]; |
| |
| How would these attributes map to the other built-in attributes? |
| That would depend on the implementation. As with ARB_vertex_program, |
| some implementations could choose to alias such generate vertex attributes |
| with conventional vertex attributes (color, fog coord, etc.) or |
| an implementation could treat the generic attributes as disjoint |
| from the conventional vertex attributes. |
| |
| If this is unsatisfactory, the solution is to avoid using |
| glCreateShaderProgramEXT and instead use the traditional GLSL |
| approach for creating programs (create shader, compile shader, |
| attach shader, bind attributes, link shader, use shader). |
| |
| Demonstrating how to workaround this particular issue, here's |
| an example of creating and using a vertex shader for use with |
| separate shader objects that includes explicit binding of output |
| varyings to fragment data locations. First the shader: |
| |
| varying in vec4 attribA; |
| varying in vec4 attribB; |
| void main() |
| { |
| gl_Position = ftransform(); |
| gl_FrontColor = attribA; |
| gl_BackColor = attribB; |
| } |
| |
| Now creating and using a linked program from this shader where |
| attribA is initialized by vertex attribute 5 and attribB is |
| initialized by vertex attribute 7. |
| |
| const GLuint shader = glCreateShader(GL_VERTEX_SHADER); |
| if (shader) { |
| const GLint len = (GLint) strlen(aboveShaderString); |
| glShaderSource(shader, 1, &aboveShaderString, &len); |
| glCompileShader(shader); |
| const uint program = glCreateProgram(); |
| if (program) { |
| GLint compiled = FALSE; |
| glGetShaderiv(shader, COMPILE_STATUS, &compiled); |
| if (compiled) { |
| glAttachShader(program, shader); |
| |
| // Crucial code that glCreateShaderProgramEXT doesn't do |
| glBindAttribLocation(program, 5, "attribA"); |
| glBindAttribLocation(program, 7, "attribB"); |
| |
| glLinkProgram(program); |
| glDetachShader(program, shader); |
| |
| // Show this program can actually be used as a vertex shader |
| glUseShaderProgramEXT(GL_VERTEX_SHADER, program); |
| } |
| } |
| glDeleteShader(shader); |
| return program; |
| } else { |
| return 0; |
| } |
| |
| Optionally, the glDetachShader and glDeleteShader commands could |
| be removed to allow this program to be re-linked after different |
| glBindAttribLocation calls. |
| |
| 16. Can you use glBindFragDataLocation to direct varying output |
| variables from a fragment shader program created by |
| glCreateShaderProgramEXT to specific color buffers? |
| |
| RESOLVED: NO for much the same reason you can't do this with |
| attributes as described in issue 15. But you could create the |
| program with the standard GLSL creation process where you attach |
| your own shaders and relink. |
| |
| For fragment shader programs created with |
| glCreateShaderProgramEXT, there is already the gl_FragData[] |
| builtin to output to numbered color buffers. For integer |
| framebuffers, we would need to add: |
| |
| varying out ivec4 gl_IntFragData[]; |
| |
| User-defined output fragment shader varyings can still be used |
| as long as the application is happy with the linker-assigned |
| locations. |
| |
| Demonstrating how to workaround this particular issue, here's |
| an example of creating and using a fragment shader for use with |
| separate shader objects that includes explicit binding of output |
| varyings to fragment data locations. First the shader: |
| |
| varying out ivec4 bufferA; |
| varying out ivec4 bufferB; |
| void main() |
| { |
| bufferA = ivec4(1,2,3,4); |
| bufferB = ivec4(5,6,7,8); |
| } |
| |
| Now creating and using a linked program from this shader where |
| bufferA outputs to color buffer 0 and bufferB outputs to color |
| buffer 1: |
| |
| const GLuint shader = glCreateShader(GL_FRAGMENT_SHADER); |
| if (shader) { |
| const GLint len = (GLint) strlen(aboveShaderString); |
| glShaderSource(shader, 1, &aboveShaderString, &len); |
| glCompileShader(shader); |
| const uint program = glCreateProgram(); |
| if (program) { |
| GLint compiled = FALSE; |
| glGetShaderiv(shader, COMPILE_STATUS, &compiled); |
| if (compiled) { |
| glAttachShader(program, shader); |
| |
| // Crucial code that glCreateShaderProgramEXT doesn't do |
| glBindFragDataLocation(program, 0, "bufferA"); |
| glBindFragDataLocation(program, 1, "bufferB"); |
| |
| glLinkProgram(program); |
| glDetachShader(program, shader); |
| |
| // Show this program can actually be used as a fragment shader |
| glUseShaderProgramEXT(GL_FRAGMENT_SHADER, program); |
| } |
| } |
| glDeleteShader(shader); |
| return program; |
| } else { |
| return 0; |
| } |
| |
| Optionally, the glDetachShader and glDeleteShader could be |
| removed to allow this program to be re-linked after different |
| glBindFragDataLocation calls. |
| |
| 17. Can you output varyings from a seperate shader program created |
| with glCreateShaderProgramEXT? |
| |
| RESOLVED: No. |
| |
| glTransformFeedbackVaryings requires a re-link to take effect on a |
| program. glCreateShaderProgramEXT detaches and deletes the shader |
| object use to create the program so a glLinkProgram will fail. |
| |
| You can still create a vertex or geometry shader program |
| with the standard GLSL creation process where you could use |
| glTransformFeedbackVaryings and glLinkProgram. |
| |
| 18. I just don't get it? Why is it such a big deal to just require |
| apps to link all their vertex and fragment shaders together? |
| Please explain a situation where mix-and-match shaders is |
| substantially better than GLSL as it exists without this |
| extension? |
| |
| RESOLUTION: Consider the (not uncommon) case of a vertex shader |
| for skinning an character. The vertex shader is used in four |
| distinct types of rendering passes, each using the one vertex |
| shader but different fragment shaders. |
| |
| For GLSL today, this situation today requires 4 program objects, |
| each containing the one vertex shader paired with each one of |
| the fragment shaders. |
| |
| The one vertex shader has an array of dozens of skinning matrices |
| along with numerous other uniform parameters. |
| |
| Each fragment shader has its own different set of uniforms too. |
| |
| Each GLSL program object has its own (combined) set of GLuint |
| locations for the active uniforms of the vertex and fragment |
| shaders objects linked into the particular program object. |
| |
| The locations for a given program object are arbitrary and |
| the location values of two distinct program objects have no |
| correlation. This is true even when they each link in the same |
| vertex shader (or alternatively same fragment shader). |
| |
| Now the application is saddled with the burden of managing |
| distinct location values for the same vertex shader skinning |
| matrices and other uniform variables as well as making sure |
| the values of these variables are mirroed over all four program |
| objects containing the skinning vertex shader. |
| |
| What's worse is despite all the program objects being loaded |
| with the same vertex shader uniform variables for skinning, the |
| driver is exceedingly unlikely to recoginize that binding from |
| one of these program objects to another is going to result in |
| no actual vertex shader state change. Noticing that the uniform |
| vertex shader variables are changing in lock-step over a series |
| of program objects (when the uniform fragment shader variables |
| ARE allowed to diverge) is exceedingly expensive. |
| |
| This situation is simple to optimize with mix-and-match shaders |
| because there is just a single vertex shader to worry about. |
| It's only the current fragment shader program that is changing |
| so only the fragment shader state must be updated/re-validated. |
| |
| It's also much easier and less expensive for the application to |
| update the vertex shader state because there is just one copy |
| of it to update. |
| |
| 19. In case of indirect rendering, should glCreateShaderProgramEXT |
| explicitly send string length parameter to server? |
| |
| PROPOSED: Yes. Although source code passed to |
| glCreateShaderProgramEXT is NUL terminated, the server can not |
| safely rely on the client to terminate the string so it must |
| add the NUL terminator before passing the protocol buffer to |
| the GL command processor. The string length is needed to do this |
| accurately. |
| |
| 20. Can glCreateShaderProgramEXT support command larger than the |
| maximum command length supported by a single command? |
| |
| PROPOSED: Yes. Source code passed to glCreateShaderProgramEXT is |
| unbounded. Command length can be more than the maximum command |
| length supported by a single command. Support for "large single" |
| command needs to be added. |
| |
| |
| |
| Revision History |
| |
| Rev. Date Author Changes |
| ---- -------- -------- ---------------------------------------- |
| 1 11/06/08 mjk Initial revision |
| 2 11/10/08 mjk add glCreateShaderProgramEXT |
| 3 11/12/08 mjk fixed glCreateShaderProgramEXT |
| add issues 12 and 13 |
| 4 11/14/08 mjk issues 13 through 17 |
| 5 12/03/08 mjk glActiveProgram replaces |
| GL_UNIFORM_SHADER_EXT |
| 6 04/01/09 mjk corrections from Jason Green |
| 7 08/12/09 mjk Marked as shipping, resolve and |
| improve issues 15 & 16 |
| 8 09/09/09 mjk Assign number |
| 9 09/09/09 mjk Fix transposed page number |
| 10 24/02/10 srahman added glx protocol for |
| glCreateShaderProgramEXT |
| added issues 19 and 20 |
| 11 03/07/13 Jon Leech Added note about the unrelated OpenGL ES |
| extension of the same name. |