Difference between revisions of "GLSL Object"

From OpenGL Wiki
Jump to navigation Jump to search
(Adding a page on GLSL objects.)
 
m (Bot: Updating section links to use redirects.)
 
(37 intermediate revisions by 3 users not shown)
Line 1: Line 1:
'''GLSL Objects''' are objects in the OpenGL API that encapsulate the compiled, linked programs that execute portions of the [[OpenGL Pipeline]]. These objects are written in the [[OpenGL Shading Language]] (GLSL). Though they are called objects, they do ''not'' fit within the [[OpenGL Objects]] paradigm.
+
A '''GLSL Object''' is an object in the OpenGL API that encapsulates the compiled or linked [[Shader]]s that execute portions of the [[Rendering_Pipeline_Overview|OpenGL Pipeline]]. These objects represent code written in the [[OpenGL Shading Language]] (GLSL). Though they are called "objects", most of them do ''not'' fit within the [[OpenGL Object]] paradigm.
  
== GLSL compilation model ==
+
== Program objects ==
  
GLSL is quite unique among shading languages due to its compilation model. Most shading languages use a simpler, one-stage model: you give it a string representing a shader for one of the shader stages, and it gives you a shader object that you can bind to the context and render with.
+
A Program Object represents fully processed executable code, in the [[OpenGL Shading Language]], for one or more [[Shader]] stages. A program object is an object in OpenGL, but it does not use the standard [[OpenGL Object|OpenGL Object model.]]
  
GLSL uses a more complicated model based on the compilation of C programs. In C, a compilation unit, typically a single source file that may include several external header files, is compiled into an object file. A number of object files are then linked into a single program.
+
=== Creation ===
 +
{{main|Shader Compilation}}
  
GLSL operates in a similar fashion. A set of source files, given as a series of strings, are compiled into a shader object. This is the analog of an object file. Unlike typical shading languages, there is no requirement that this shader object represent a full shader stage. The only limitation is that it can only compile code that is appropriate for a single, specific shader stage.
+
Empty program objects are created with this function:
  
Shader objects are useless in that form, just as object files from compiled C programs are useless directly. Shader objects must be linked into a single program object. Unlike most shader languages, the program objects contain ''all'' programmable stages at once. Only one program can be bound for rendering at any one time, and it is illegal for a program object to omit any required stages entirely. Required stages are those for which there is no non-shader equivalent.
+
{{funcdef|GLuint {{apifunc|glCreateProgram}}()}}
  
{{legacy note|In compatibility mode, none of the stages are required, as fixed-functionality can always replicate them.}}
+
This will return an empty program object. Programs are deleted with {{apifunc|glDeleteProgram}}.
  
== Terminology ==
+
Empty program objects must then be filled in with executable code. This is done by [[Shader Compilation|compiling linking shaders into the program]], or by [[Program Binary|uploading binary, pre-compiled data from a previously-created program object]].
  
Because of GLSL's unique compilation model, GLSL uses unique terminology.
+
==== Pre-link setup ====
 +
{{main|Program Pre-Link Setup}}
  
According to GLSL's standard terminology, a ''shader'' is just a compiled set of strings for a particular programmable stage; it does not even need to have the complete code for that stage. A ''program'' is a fully linked program that covers multiple programmable stages.
+
Before performing the linking steps for a program, it is sometimes important to provide certain settings that affect the final linking step. These operations assign resource numbers to interface elements in a shader. More recent OpenGL features allow these resources to be assigned in the shader text itself.
  
== Shader and program objects ==
+
=== Introspection ===
 +
{{main|Program Introspection}}
  
Since GLSL's compilation model has 2 separate concepts, shaders and programs, there are 2 kinds of objects: shader objects and program objects. Shader objects represent compiled shaders, while program objects represent fully linked programs.
+
After a program has been successfully linked, information about the various interfaces can be queried. This allows the user to know how to set [[Uniform]] values, determine which [[Vertex Attribute]]s the program takes (if any), and other similar resources.
  
Neither of these object types conforms to the standard [[OpenGL Objects]] paradigm. Rather than using a state-based methadology for most of their functions, they use a more object-based API. The compilation, linking, and state access functions for these objects all take the object as a parameter, rather than requiring that the object be bound to the context before use.
+
=== State setting ===
  
== Object creation ==
+
Outside of the state used by the [[#Pre-link setup|pre-link setup]], program objects have the following mutable state:
  
Shader objects are created with a call to:
+
* The current values of all [[Uniform Location|''active'' uniform variables]]
 +
** This includes the binding indices for any [[Opaque Type]]s, which are declared as global uniform values.
 +
* The current binding indices for any [[Interface_Block_(GLSL)#Uniform_blocks|Uniform blocks]].
 +
* The current binding indices for any [[Manual Interface Block Binding|Shader storage blocks]].
  
  GLuint glCreateShader(GLenum ''type'');
+
The last two pieces of state only need to be set if you did not [[Interface Block Binding|set them directly in the shader]].
  
The ''type'' field refers to the kind of shader object you wish to compile. A shader object can be of type GL_VERTEX_SHADER, GL_FRAGMENT_SHADER, or GL_GEOMETRY_SHADER. Once created, this object can only ever be used for shaders of that particular type.
+
{{note|The current state for any [[Subroutine Uniform]]s are explicit ''not'' part of any program object's state.}}
  
{legacy note|In pre-OpenGL 3.1, you could ignore the glGen* functions, using any non-zero unsigned 32-bit integer as an object name. This was true for any OpenGL Object. However, because shader objects are not OpenGL Objects, you ''cannot'' do this, even in GL 2.0.}
+
== Shader objects ==
  
They are deleted by calling:
+
Shader objects represent compiled [[GLSL]] code for a single [[Shader Stage|shader stage]]. The code may not be the complete code for a shader stage; the complete code can be assembled from multiple shader objects that contain source code for the same stage. Shader objects are not [[OpenGL Object]]s, but they are objects.
  
  void glDeleteShader(GLuint ''shader'');
+
Shader objects are created with this function:
  
Similarly, program objects are created and deleted with:
+
{{funcdef|GLuint {{apifunc|glCreateShader}}(GLenum {{param|shaderType}});}}
  
  GLuint glCreateProgram();
+
The {{param|shaderType}} defines which shader stage the shader object holds code for. The enumerator is one of the standard [[Shader Stage|shader stage enumerators]].
  void glDeleteProgram(GLuint ''program'');
 
  
Note that the creation and deletion functions work one at a time, unlike those for regular OpenGL Objects.
+
Shader objects do not store very much state. They contain a set of strings, which represent the source code for that shader stage (retrieved with {{apifunc|glGetShaderSource}}). They also store whether the most recent compilation to this shader object was successful (retrieved with {{apifunc|glGetShader|(GL_COMPILE_STATUS)}}), as well as error messages generated by that compilation if it failed (retrieved with {{apifunc|glGetShaderInfoLog}}).
  
== Shader compiling ==
+
Conceptually, they lastly store the GLSL object code from the most recent compilation. This latter state cannot be queried, but it is accessed by the program object linking process when linking with one or more shader objects.
  
Compiling a shader object is pretty simple. Before you can compile a shader, you must add strings to it. This is done with this command:
+
Shader objects are deleted with the {{apifunc|glDeleteShader}} function. Though they are not [[OpenGL Object]]s, they can be [[Object Orphaning|orphaned]], if they are attached to a program object before they are deleted.
  
  void glShaderSource(GLuint ''shader'', GLsizei ''count'', const char **''string'', const int *''length'');
+
== Program pipeline objects ==
  
The ''shader'' parameter is a previously created shader object. You can compile multiple strings in a single shader. This works exactly like appending these strings to one another, in the order given in the array. ''count'' tells how many strings are in the array, ''string'' is the array of strings to compile, and ''length'' is an array of lengths of those strings. ''length'' can be NULL; if it is, then all of the strings in ''string'' must be NULL-terminated. Otherwise, the lengths of the strings will be taken from the length value. If one of the elements in ''length'' is negative, then the corresponding string must be NULL-terminated.
+
Successfully linked separable programs are intended to be used with program pipeline objects. A pipeline object is an [[OpenGL Object]] that [[Container Object|contains]] separable program objects. When a [[#Program usage|pipeline is active]], the [[Shader Stage]] code defined by the programs in the pipeline become the shader stages used in various operations.
  
Calling this function will also undo any previous calls to this function for this command. So calling this multiple times will not add multiple strings; that's why the function intrinsically takes multiple strings.
+
Unlike program or shader objects, pipeline objects follow the standard [[OpenGL Object]] conventions. Therefore, there is a {{apifunc|glGenProgramPipelines}} function to create new pipeline names, a {{apifunc|glDeleteProgramPipelines}} to delete them, and a {{apifunc|glBindProgramPipeline}} to bind it to the context. Program pipeline objects do not have targets, so the last function only takes the pipeline to be bound.
  
Note that, like any other OpenGL function that takes pointers, the information in those pointers is copied to the OpenGL context before the function returns. Therefore, you may free this memory afterward.
+
However, unlike most OpenGL objects, when a name is created for a pipeline, the object's data is also created. So you do not have to bind the pipeline before trying to use it. Similar to [[Sampler Object]]s, program pipeline objects should only be bound when you intend to render with them (or set uniforms through them, [[#Uniforms and pipelines|as described below]]).
  
Once strings have been set, you can then compile the shader:
+
The primary state in program pipeline objects are the list of programs that contain the code for the various shader stages. This state is set by this function:
  
  void glCompileShader(GLuint ''shader'');
+
void {{apifunc|glUseProgramStages}}(GLuint {{param|pipeline}}, GLbitfield {{param|stages}}, GLuint {{param|program}});
  
This does not return a value; you can query the success or failure of the compilation via glGetShaderiv. See the section on [[#Error handling]] for this.
+
The given {{param|pipeline}} will get the shader code for the shader stages defined by the bitfield {{param|stages}} from the given {{param|program}}. The {{param|program}} parameter must either be 0 or a separable program that has been successfully linked as such.
  
A shader object, once it has successfully compiled, can be compiled with a different set of strings. All you need to do is call glShaderSource and glCompileShader again. This is not advisable, however. It is preferable to simply delete the shader object and build a new one, as recompiling the shader will likely not have the effect you intend.
+
The {{param|stages}} bitfield determines which [[Shader Stage]]s from {{param|program}} will provide code for those shader stages in the pipeline. These bits can be a combination of:
  
For example, if you have a program and you attach a shader to it, recompiling the shader with new code will not update the program. This is exactly like it is for object files on the disk; it doesn't matter that you change a .o file once you've already used it to generate the executable. You must re-link the executable manually in order for the changes to take effect.
+
* {{enum|GL_VERTEX_SHADER_BIT}}
 +
* {{enum|GL_TESS_CONTROL_SHADER_BIT}}
 +
* {{enum|GL_TESS_EVALUATION_SHADER_BIT}}
 +
* {{enum|GL_GEOMETRY_SHADER_BIT}}
 +
* {{enum|GL_FRAGMENT_SHADER_BIT}}
 +
* {{enum|GL_COMPUTE_SHADER_BIT}}.
  
== Program linking ==
+
The bitfield can also be {{enum|GL_ALL_SHADER_BITS}}, which is equivalent to all of the above.
  
Linking a program is not as simple as compiling a shader. The linking process involves more than just taking a collection of compiled shader objects and building a program from them. Though that is the first step.
+
The stages of {{param|program}} attached to the {{param|pipeline}} are only those stages specified by the bitfield. If {{param|program}} is 0, then the specified stages are cleared from the pipeline.
  
In order to link a program, you must ''attach'' one or more compiled shader objects to the program. This is done with this API:
+
Program pipeline objects are [[OpenGL_Object#Container object|container objects]]. As such, they cannot be [[Object Sharing|shared across multiple OpenGL contexts.]]
  
  void glAttachProgram(GLuint ''program'', GLuint ''shader'');
+
=== Uniforms and pipelines ===
  
This will cause the shader object ''shader'' to become attached to the program object ''program''. A shader object can be attached to any number of program objects. The shader object, due to being attached to the program object, will continue to exist even if you delete the shader object. It will only be deleted by the system when it is no longer attached to any program object (and when the user has asked to delete it, of course). Even so, it is not a good idea to refer to shader objects after deleting them.
+
{{recommend|The following explains a highly convoluted way to use {{apifunc|glBindProgramPipeline}} to allow the user to set uniform state for one of the programs within a pipeline. You are ''strongly'' advised to ignore this section. Instead, when writing new code, use {{apifunc|glProgramUniform}} to set uniforms directly into programs without having to bind or use the program. Only use this if you absolutely must remain backwards compatible with some functions that set uniforms on a program that is currently in use, and yet somehow can't temporarily use {{apifunc|glUseProgram}}.}}
  
You do not have to explicitly detach shader objects, even after linking the program. However, if you wish to do so, you may use this function:
+
{{apifunc|glUniform}} changes uniform state on the currently used program. However, with separate programs and program pipelines, the definition of "[[#Program usage|currently used program]]" is much more complicated. It works as follows.
  
  void glDetachProgram(GLuint ''program'', GLuint ''shader'');
+
If no program object is in use via {{apifunc|glUseProgram}}, then the currently bound program pipeline is checked. If there is a bound program pipeline, then the program object which is considered "active" in that pipeline is used as the destination for {{apifunc|glUniform}} calls.
  
The next step in linking the program is to provide attribute indices for any vertex attributes. This is only important if you have a vertex shader as part of the program.
+
The active program for a pipeline is set by this function:
  
This step is also optional. If you wish, OpenGL can automatically assign your vertex attributes to an index. However, since you must know this index in order to set up your [[Vertex Array Objects|VAO]] correctly, and you will likely want to be able to mix and match VAOs and programs as much as you want, it is best to pick your own vertex attribute indices.
+
void {{apifunc|glActiveShaderProgram}}(GLuint {{param|pipeline}}, GLuint {{param|program}});
  
To do this, call this API before linking the program:
+
{{param|program}} must be a valid, successfully linked program object. It ''may not be zero''; you cannot unset an active program once you set it onto the pipeline.
  
  void glBindAttribLocation(GLuint ''program'', GLuint ''index'', const char *''name'');
+
{{note|Silly though it may seem, {{param|program}} ''does not'' have to be attached to {{param|pipeline}} for this to work. A pipeline can have a completely unrelated program as its active program.}}
 
 
The ''index'' is the attribute value you want to assign, and ''name'' is the string name of the attribute in the vertex shader that you want to use. The binding this function creates only takes effect when the program is linked. The attribute ''name'' does not have to actually be in the linked program; this allows you to set up a global mapping of names to indices and simply always use them for every program you create.
 
 
 
If one is rendering to a framebuffer (as opposed to a vertex buffer through transform feedback), then the output values must be mapped to the current framebuffer's draw buffer indices. If the fragment shader only writes to one user-defined output, then this output will be automatically bound to output index 0. Otherwise, the output indices will be automatically generated, just as for vertex shader inputs.
 
 
 
Automatic generation of output indices is less useful than for attribute indices. That is because you are far more likely to need to use multiple program with the same framebuffer, and the changes made by glDrawBuffers is part of the framebuffer's state. If you do not wish to change this parameter for every use of a program, then you are advised to manually assign output indices for all of your programs.
 
 
 
To do this, call this API before linking:
 
 
 
  void glBindFragDataLocation(GLuint ''program'', GLuint ''colorNumber'', const char *''name'');
 
 
 
The ''colorNumber'' is the index into the glDrawBuffers list that the output named ''name'' will be written into.
 
 
 
If you are instead intending to use this program for [[Transform Feedback|transform feedback]], then you must tell the program which outputs from the last shader stage should be written to the buffer objects.
 
 
 
To do this, call this API before linking:
 
 
 
  void glTransformFeedbackVaryings(GLuint ''program'', GLsizei ''count'', const char **''varyings'', GLenum ''bufferMode'');
 
 
 
The ''varyings'' is a string array of ''count'' elements. These named outputs, in order, will be written to the buffer. The ''bufferMode'' says whether the written attributes will be interleaved or written separately to the buffer.
 
 
 
Once all of this has been set up as the user wishes, then you may call:
 
 
 
  void LinkProgram(GLuint ''program'');
 
 
 
This will link the program.
 
 
 
=== Error handling ===
 
 
 
Compiling and linking can cause errors. Unlike most OpenGL Errors however, these errors are delivered in the form of text.
 
 
 
To check to see if a shader successfully compiled, call <code>glGetShaderiv(''shader'', GL_COMPILE_STATUS, &bDidCompile)</code>. The integer pointer will be filled with GL_TRUE if the compilation was successful and GL_FALSE if it was not. Similarly, to check to see if a program linked, call <code>glGetProgramiv(''program'', GL_LINK_STATUS, &bDidLink)</code>.
 
 
 
Compiling and linking, whether successful or not, will generate a textual log. The log will contain warnings and errors, as appropriate to the shader and program in question. The length of the log can be queried with glGetShader/Programiv with GL_INFO_LOG_LENGTH as the parameter. The logs themselves can be queried with this function:
 
 
 
void glGetShaderInfoLog( GLuint ''shader'', GLsizei ''bufSize'', GLsizei *''length'', char *''infoLog'' );
 
void glGetProgramInfoLog( GLuint ''program'', GLsizei ''bufSize'', GLsizei *''length'', char *''infoLog'' );
 
 
 
This will cause the ''infoLog'' buffer (of size ''bufSize'') to be filled in with the log. If ''length'' is non-NULL, it will be filled in with the number of characters written to ''infoLog''.
 
  
 
== Program usage ==
 
== Program usage ==
  
The only thing you can use shader objects for is to make programs. Program objects however, have many uses.
+
In order to use the shader stages that a program encapsulates, you must first bind the program object to the [[OpenGL Context]]. Unlike standard [[OpenGL Object]]s, program objects are bound to the context with this function:
 
 
To bind a program to the context for rendering, call:
 
 
 
  void glUseProgram(GLuint ''program'');
 
 
 
As with the usual glBind* calls, this will cause ''program'' to become the actively bound program and cause the previously bound program to be unbound. And just as with the usual glBind* calls, binding the 0 program object will cause the program to be unbound.
 
 
 
Program objects store the state of [[GLSL Uniforms|GLSL Uniform values]]. These can be queried and set through program objects.
 
 
 
You can retrieve information about the attribute and fragment data location bindings as well.
 
 
 
Like uniforms, attributes can be active or inactive. Attributes that are unused are inactive; they do not have a binding. The number of active attributes in a program can be retrieved with <code>glGetProgramiv</code> with GL_ACTIVE_ATTRIBUTES.
 
  
To retrieve information about an attribute, call this function:
+
{{funcdef|void {{apifunc|glUseProgram}}(GLuint {{param|program}});}}
  
  void glGetActiveAttrib( GLuint ''program'', GLuint ''index'', GLsizei ''bufSize'', GLsizei *''length'', GLint *''size'', GLenum *''type'', char *''name'' );
+
This will bind the {{param|program}} to the current context, unbinding the previously bound program object. If it is zero, then no program is bound to the context.
  
The ''index'' is a number on the half-open range [0, GL_ACTIVE_ATTRIBUTES); it represents a particular active attribute. ''name'' will be filled in with the name of the attribute; ''bufSize'' is the size of this character array. If ''length'' is not NULL, it will be filled in with the number of characters written to ''name''. The ''size'' will be filled with the number of elements in the attribute array, if the attribute is an array type. Otherwise, it will be set to 1. The ''type'' will be set to the OpenGL enumeration for the GLSL type of the attribute.
+
While a program object is bound to the context, all [[Vertex Rendering|drawing commands]] (and [[Compute Dispatch|compute dispatch operations]] with {{require|4.3|compute_shader}}) will be rendered using the shaders linked into that program, as well as whatever state is set into that program.
  
To get the attribute location (the one used by [[Vertex Specification|glVertexAttribPointer]], not the ''index'' field used above), we use this function:
+
If {{require|4.1|separate_shader_objects}} is available and you wish to use the programs within a program pipeline, the first step is to unbind any programs with {{apifunc|glUseProgram|(0)}}. If a program is bound with {{apifunc|glUseProgram}}, then any bound program pipelines will be ignored.
  
  GLint glGetAttribLocation( GLuint ''program'', const char *''name'' );
+
Then, bind the program pipeline object with:
  
If ''name'' is not an active attribute in ''program'', the function will return -1.
+
{{funcdef|{{apifunc|glBindProgramPipeline}}(GLuint {{param|pipeline}});}}
  
Similarly, to get the fragment data location we use this function:
+
{{param|pipeline}} is the program pipeline object to bind. When this is done, the shader code and uniform state will come from the programs stored within the pipeline object.
  
  GLint glGetFragDataLocation( GLuint ''program'', const char *''name'' );
+
== Reference ==
  
Again, if ''name'' is not a fragment data location in ''program'', the function returns -1.
+
* [[:Category:Core API Ref Shader Program Creation]]: Reference manual for all core OpenGL functions that create shaders, programs, and program pipeline objects.
 +
* [[:Category:Core API Ref Shader Program Query]]: Reference manual for all core OpenGL functions that get information from shaders and programs. These are used to investigate attributes, uniforms, etc.
 +
* [[:Category:Core API Ref Shader Program Usage and State‏‎]]: Reference manual for all core OpenGL functions that set state on programs and program pipeline objects, as well as bind and use them.
  
 +
[[Category:Shaders]]
 
[[Category:OpenGL Shading Language]]
 
[[Category:OpenGL Shading Language]]

Latest revision as of 16:35, 6 May 2015

A GLSL Object is an object in the OpenGL API that encapsulates the compiled or linked Shaders that execute portions of the OpenGL Pipeline. These objects represent code written in the OpenGL Shading Language (GLSL). Though they are called "objects", most of them do not fit within the OpenGL Object paradigm.

Program objects

A Program Object represents fully processed executable code, in the OpenGL Shading Language, for one or more Shader stages. A program object is an object in OpenGL, but it does not use the standard OpenGL Object model.

Creation

Empty program objects are created with this function:

GLuint glCreateProgram()

This will return an empty program object. Programs are deleted with glDeleteProgram.

Empty program objects must then be filled in with executable code. This is done by compiling linking shaders into the program, or by uploading binary, pre-compiled data from a previously-created program object.

Pre-link setup

Before performing the linking steps for a program, it is sometimes important to provide certain settings that affect the final linking step. These operations assign resource numbers to interface elements in a shader. More recent OpenGL features allow these resources to be assigned in the shader text itself.

Introspection

After a program has been successfully linked, information about the various interfaces can be queried. This allows the user to know how to set Uniform values, determine which Vertex Attributes the program takes (if any), and other similar resources.

State setting

Outside of the state used by the pre-link setup, program objects have the following mutable state:

The last two pieces of state only need to be set if you did not set them directly in the shader.

Note: The current state for any Subroutine Uniforms are explicit not part of any program object's state.

Shader objects

Shader objects represent compiled GLSL code for a single shader stage. The code may not be the complete code for a shader stage; the complete code can be assembled from multiple shader objects that contain source code for the same stage. Shader objects are not OpenGL Objects, but they are objects.

Shader objects are created with this function:

GLuint glCreateShader(GLenum shaderType​);

The shaderType​ defines which shader stage the shader object holds code for. The enumerator is one of the standard shader stage enumerators.

Shader objects do not store very much state. They contain a set of strings, which represent the source code for that shader stage (retrieved with glGetShaderSource). They also store whether the most recent compilation to this shader object was successful (retrieved with glGetShader(GL_COMPILE_STATUS)), as well as error messages generated by that compilation if it failed (retrieved with glGetShaderInfoLog).

Conceptually, they lastly store the GLSL object code from the most recent compilation. This latter state cannot be queried, but it is accessed by the program object linking process when linking with one or more shader objects.

Shader objects are deleted with the glDeleteShader function. Though they are not OpenGL Objects, they can be orphaned, if they are attached to a program object before they are deleted.

Program pipeline objects

Successfully linked separable programs are intended to be used with program pipeline objects. A pipeline object is an OpenGL Object that contains separable program objects. When a pipeline is active, the Shader Stage code defined by the programs in the pipeline become the shader stages used in various operations.

Unlike program or shader objects, pipeline objects follow the standard OpenGL Object conventions. Therefore, there is a glGenProgramPipelines function to create new pipeline names, a glDeleteProgramPipelines to delete them, and a glBindProgramPipeline to bind it to the context. Program pipeline objects do not have targets, so the last function only takes the pipeline to be bound.

However, unlike most OpenGL objects, when a name is created for a pipeline, the object's data is also created. So you do not have to bind the pipeline before trying to use it. Similar to Sampler Objects, program pipeline objects should only be bound when you intend to render with them (or set uniforms through them, as described below).

The primary state in program pipeline objects are the list of programs that contain the code for the various shader stages. This state is set by this function:

void glUseProgramStages(GLuint pipeline​, GLbitfield stages​, GLuint program​);

The given pipeline​ will get the shader code for the shader stages defined by the bitfield stages​ from the given program​. The program​ parameter must either be 0 or a separable program that has been successfully linked as such.

The stages​ bitfield determines which Shader Stages from program​ will provide code for those shader stages in the pipeline. These bits can be a combination of:

  • GL_VERTEX_SHADER_BIT
  • GL_TESS_CONTROL_SHADER_BIT
  • GL_TESS_EVALUATION_SHADER_BIT
  • GL_GEOMETRY_SHADER_BIT
  • GL_FRAGMENT_SHADER_BIT
  • GL_COMPUTE_SHADER_BIT.

The bitfield can also be GL_ALL_SHADER_BITS, which is equivalent to all of the above.

The stages of program​ attached to the pipeline​ are only those stages specified by the bitfield. If program​ is 0, then the specified stages are cleared from the pipeline.

Program pipeline objects are container objects. As such, they cannot be shared across multiple OpenGL contexts.

Uniforms and pipelines

Recommendation: The following explains a highly convoluted way to use glBindProgramPipeline to allow the user to set uniform state for one of the programs within a pipeline. You are strongly advised to ignore this section. Instead, when writing new code, use glProgramUniform to set uniforms directly into programs without having to bind or use the program. Only use this if you absolutely must remain backwards compatible with some functions that set uniforms on a program that is currently in use, and yet somehow can't temporarily use glUseProgram.

glUniform changes uniform state on the currently used program. However, with separate programs and program pipelines, the definition of "currently used program" is much more complicated. It works as follows.

If no program object is in use via glUseProgram, then the currently bound program pipeline is checked. If there is a bound program pipeline, then the program object which is considered "active" in that pipeline is used as the destination for glUniform calls.

The active program for a pipeline is set by this function:

void glActiveShaderProgram(GLuint pipeline​, GLuint program​);

program​ must be a valid, successfully linked program object. It may not be zero; you cannot unset an active program once you set it onto the pipeline.

Note: Silly though it may seem, program​ does not have to be attached to pipeline​ for this to work. A pipeline can have a completely unrelated program as its active program.

Program usage

In order to use the shader stages that a program encapsulates, you must first bind the program object to the OpenGL Context. Unlike standard OpenGL Objects, program objects are bound to the context with this function:

void glUseProgram(GLuint program​);

This will bind the program​ to the current context, unbinding the previously bound program object. If it is zero, then no program is bound to the context.

While a program object is bound to the context, all drawing commands (and compute dispatch operations with OpenGL 4.3 or ARB_compute_shader) will be rendered using the shaders linked into that program, as well as whatever state is set into that program.

If OpenGL 4.1 or ARB_separate_shader_objects is available and you wish to use the programs within a program pipeline, the first step is to unbind any programs with glUseProgram(0). If a program is bound with glUseProgram, then any bound program pipelines will be ignored.

Then, bind the program pipeline object with:

glBindProgramPipeline(GLuint pipeline​);

pipeline​ is the program pipeline object to bind. When this is done, the shader code and uniform state will come from the programs stored within the pipeline object.

Reference