blob: 6d40a82db4c386c587a197a0e86406b4ee9849f9 [file] [log] [blame]
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 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,
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 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. 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.