Difference between revisions of "GLSL Object"

From OpenGL Wiki
Jump to: navigation, search
(Better wording.)
m (Bot: Updating section links to use redirects.)
 
(16 intermediate revisions by 3 users not shown)
Line 1: Line 1:
A '''GLSL Object''' is an object in the OpenGL API that encapsulates the compiled or linked programs 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", they do ''not'' fit within the [[OpenGL Object]] 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 the ''full code'' for a shader stage. The only limitation is that it can only contain 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. What makes GLSL's model unique is that multiple shader objects from different stages can be linked into a single program. So [[Vertex Shader]] and [[Fragment Shader]] can be linked into a single program.
+
{{funcdef|GLuint {{apifunc|glCreateProgram}}()}}
  
Note that if a shader stage is missing it's `main` function in the linker (ie: the program isn't given a shader object that defines `main` for that stage), then the stage is effectively not present in the program. It is possible to render with a program that only provides a [[Vertex Shader]], but you need to {{apifunc|glEnable|(GL_RASTERIZER_DISCARD)}} in order to get away with it.
+
This will return an empty program object. Programs are deleted with {{apifunc|glDeleteProgram}}.
  
Normally, you can only render with a single program, and thus a single program must combine every shader stage you wish to render with. However, if you have access to GL 4.1 or {{extref|separate_shader_objects}}, you may attach multiple programs, all with different shader stages, to a single program pipeline. This makes it easier to mix-and-match programs. See the [[#Program separation|Program separation section]] for more details.
+
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]].
  
== Terminology ==
+
==== Pre-link setup ====
 +
{{main|Program Pre-Link Setup}}
  
Because of GLSL's unique compilation model, GLSL uses unique terminology.
+
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.
  
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.
+
=== Introspection ===
 
+
{{main|Program Introspection}}
=== Shader and program objects ===
 
 
 
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.
 
 
 
Neither of these object types conforms to the standard [[OpenGL Objects]] paradigm. Rather than using a state-based methodology 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.
 
 
 
== Object creation ==
 
 
 
A shader object is created by a call to:
 
 
 
  GLuint {{apifunc|glCreateShader}}(GLenum {{param|type}});
 
 
 
The {{param|type}} field refers to the kind of shader object you wish to compile. A shader object can be of type {{enum|GL_VERTEX_SHADER}}, {{enum|GL_FRAGMENT_SHADER}}, or {{enum|GL_GEOMETRY_SHADER}}. If OpenGL 4.0 or {{extref|tessellation_shader}} is available, then {{enum|GL_TESS_CONTROL_SHADER}} and {{enum|GL_TESS_EVALUATION_SHADER}} may be used. Once created, this object can only ever be used for shaders of that particular type.
 
 
 
{{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.}}
 
 
 
They are deleted by calling:
 
 
 
  void {{apifunc|glDeleteShader}}(GLuint {{param|shader}});
 
 
 
Similarly, program objects are created and deleted with:
 
 
 
  GLuint {{apifunc|glCreateProgram}}();
 
  void {{apifunc|glDeleteProgram}}(GLuint {{param|program}});
 
 
 
{{apifunc|glCreateProgram}} does not take parameters.
 
 
 
Note that the creation and deletion functions only create one object at a time, unlike those for regular OpenGL Objects.
 
 
 
== Shader compiling ==
 
 
 
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:
 
 
 
  void {{apifunc|glShaderSource}}(GLuint {{param|shader}}, GLsizei {{param|count}}, const char **{{param|string}}, const int *{{param|length}});
 
 
 
The {{param|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. {{param|count}} tells how many strings are in the array, {{param|string}} is the array of strings to compile, and {{param|length}} is an array of lengths of those strings. {{param|length}} can be NULL; if it is, then all of the strings in {{param|string}} must be NULL-terminated. Otherwise, the lengths of the strings will be taken from the length value. If one of the elements in {{param|length}} is negative, then the corresponding string must be NULL-terminated.
 
 
 
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.
 
 
 
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.
 
 
 
Once strings have been set, you can then compile the shader:
 
 
 
  void {{apifunc|glCompileShader}}(GLuint {{param|shader}});
 
 
 
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.
 
 
 
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.
 
 
 
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.
 
 
 
== Program linking ==
 
 
 
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.
 
  
In order to link a program, you must ''attach'' one or more compiled shader objects to the program. This is done with this API:
+
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.
  
  void {{apifunc|glAttachShader}}(GLuint {{param|program}}, GLuint {{param|shader}});
+
=== State setting ===
  
This will cause the shader object {{param|shader}} to become attached to the program object {{param|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.
+
Outside of the state used by the [[#Pre-link setup|pre-link setup]], program objects have the following mutable state:
  
=== Pre-link setup ===
+
* 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]].
  
There are a number of operations that may need to be performed on programs before linking.  
+
The last two pieces of state only need to be set if you did not [[Interface Block Binding|set them directly in the shader]].
  
[[Vertex Attribute]]s for a [[Vertex Shader]] (if present in the program object) can be manually assigned an attribute index. Obviously, if no vertex shader is in the program, you do not need to assign attributes manually. Note that it is still best to [[GLSL_Type_Qualifiers#Vertex_shader_attribute_index|assign them explicitly in the shader]], where possible.
+
{{note|The current state for any [[Subroutine Uniform]]s are explicit ''not'' part of any program object's state.}}
  
To do this, call this API before linking the program:
+
== Shader objects ==
  
  void {{apifunc|glBindAttribLocation}}(GLuint {{param|program}}, GLuint {{param|index}}, const char *{{param|name}});
+
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.
  
The {{param|index}} is the attribute value you want to assign, and {{param|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 {{param|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.
+
Shader objects are created with this function:
  
If one is using a [[Fragment Shader]], the output values from the [[Fragment Shader]] must be mapped to the current [[Framebuffer Object#Multiple Render Targets|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 buffer index 0 (with dual-source index 0, when considering [[Blending#Dual Source Blending|dual-source blending]]). Otherwise, the output indices will be automatically generated, just as for vertex shader inputs.
+
{{funcdef|GLuint {{apifunc|glCreateShader}}(GLenum {{param|shaderType}});}}
  
As with vertex attributes, fragment shader output indices can be manually assigned from within the shader, and this is the preferred way to handle them. They can also be automatically generated for any outputs that are not manually assigned, though this is highly unhelpful for multiple output buffers. This is because you are far more likely to need to use multiple program with the same framebuffer, and the changes made by {{apifunc|glDrawBuffers}} is part of the framebuffer's state and can affect FBO completeness. If you do not wish to change the draw buffers every time you use a new program, then you are advised to manually assign output indices for all of your programs.
+
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]].
  
To do this without explicitly providing it in the shader, call this API before linking:
+
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}}).
  
  void {{apifunc|glBindFragDataLocation}}(GLuint {{param|program}}, GLuint {{param|colorNumber}}, const char *{{param|name}});
+
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.
  
The {{param|colorNumber}} is the index into the {{apifunc|glDrawBuffers}} list that the output named {{param|name}} will be written into.
+
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.
  
For [[Blending#Dual Source Blending|dual-source blending]], you need to be able to associate a buffer index and a dual-source index with the output. This is done with this function:
+
== Program pipeline objects ==
  
  void {{apifunc|glBindFragDataLocationIndexed}}(GLuint {{param|program}}, GLuint {{param|colorNumber}}, GLuint {{param|index}}, const char *{{param|name}});
+
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.
  
The {{param|index}} is either 0 or 1, defining which dual-source index is being assigned to the output.
+
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.
  
If you are intending to use this program for [[Transform Feedback]], then you must tell the program which outputs from the last shader stage before [[Vertex Post-Processing]] should be written to the transform feedback buffer objects.
+
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]]).
  
To do this, call this API before linking:
+
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 {{apifunc|glTransformFeedbackVaryings}}(GLuint {{param|program}}, GLsizei {{param|count}}, const char **{{param|varyings}}, GLenum {{param|bufferMode}});
+
void {{apifunc|glUseProgramStages}}(GLuint {{param|pipeline}}, GLbitfield {{param|stages}}, GLuint {{param|program}});
  
The {{param|varyings}} is a string array of {{param|count}} elements. These named outputs, in order, will be written to the buffer. The {{param|bufferMode}} says whether the written attributes will be interleaved or written separately to the buffer.
+
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.
  
=== Linking ===
+
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:
  
Once all of this has been set up as the user wishes, then you may call:
+
* {{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}}.
  
  void {{apifunc|glLinkProgram}}(GLuint {{param|program}});
+
The bitfield can also be {{enum|GL_ALL_SHADER_BITS}}, which is equivalent to all of the above.
  
This will link the program.
+
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.
  
You do not have to explicitly detach shader objects, even after linking the program. However, it is a good idea to do so once linking is complete, as otherwise the program object will keep its attached shader objects alive when you try to delete them. Shader objects can be detached with this function:
+
Program pipeline objects are [[OpenGL_Object#Container object|container objects]]. As such, they cannot be [[Object Sharing|shared across multiple OpenGL contexts.]]
  
  void {{apifunc|glDetachShader}}(GLuint {{param|program}}, GLuint {{param|shader}});
+
=== Uniforms and pipelines ===
  
If the shader no longer needs to be used, it can be deleted.
+
{{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}}.}}
  
== Error handling ==
+
{{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.
  
Compiling and linking can cause errors. Unlike most [[OpenGL Error|OpenGL errors]] however, these errors are delivered in the form of text.
+
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.
  
To check to see if a shader successfully compiled, call {{apifunc|glGetShader|iv(''shader'', GL_COMPILE_STATUS, &bDidCompile)}}. The integer pointer will be filled with {{enum|GL_TRUE}} if the compilation was successful and {{enum|GL_FALSE}} if it was not. Similarly, to check to see if a program linked, call {{apifunc|glGetProgram|iv(''program'', GL_LINK_STATUS, &bDidLink)}}.
+
The active program for a pipeline is set by this function:
  
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 {{apifunc|glGetShader}}/{{apifunc|glGetProgram}} with {{enum|GL_INFO_LOG_LENGTH}} as the parameter. The logs themselves can be queried with this function:
+
void {{apifunc|glActiveShaderProgram}}(GLuint {{param|pipeline}}, GLuint {{param|program}});
  
void {{apifunc|glGetShaderInfoLog}}( GLuint {{param|shader}}, GLsizei {{param|bufSize}}, GLsizei *{{param|length}}, char *{{param|infoLog}} );
+
{{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 {{apifunc|glGetProgramInfoLog}}( GLuint {{param|program}}, GLsizei {{param|bufSize}}, GLsizei *{{param|length}}, char *{{param|infoLog}} );
 
  
This will cause the {{param|infoLog}} buffer (of size {{param|bufSize}}, including space for the null terminator) to be filled in with the log. If {{param|length}} is non-NULL, it will be filled in with the number of characters written to {{param|infoLog}}.
+
{{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.}}
  
 
== 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 {{apifunc|glUseProgram}}(GLuint {{param|program}});
 
 
 
As with the usual glBind* calls, this will cause {{param|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. Rendering without a program (or [[#Program separation|program pipeline]] will cause errors.
 
 
 
Program objects store the state of [[GLSL Uniform|GLSL Uniform values]]. These values can be retrieved and set as normal.
 
 
 
== Program introspection ==
 
{{main|Program Introspection}}
 
 
 
You can retrieve information about the uniforms, attribute, and fragment data stored in a program. This can be used to query for locations, but it can also be used to find general information about the user-facing interfaces within a program.
 
 
 
== Program separation ==
 
{{missing}}
 
 
 
{{infobox feature
 
| name = Program Separation
 
| core = 4.1
 
| arb_extension = [http://www.opengl.org/registry/specs/ARB/separate_shader_objects.txt GL_ARB_separate_shader_objects]
 
}}
 
 
 
The above paradigm is functional, but with the increase in the number of shader stages, the combinatorial explosion of different combinations of shaders is very great. Therefore, it is possible to compile and link what is called a ''separate'' or ''separable'' program which only consists of executable code for one or more shader stages, e.g {{enum|GL_VERTEX_SHADER}}. The fact that shader stages can be separated in that manner opens the door for a technique referred to as ''mix-and-match''. This means, for instance, that the shader author can develop multiple version of a fragment shader which all use a single vertex shader. This involves creating a single, separate program for the vertex shader and multiple separate programs for the fragment shaders.
 
 
 
Having separate programs alone will not do anything. One has to define a so called ''program pipeline'', which is a container object for one or more separate programs, each of which may install shader executables for one or more shader stages.
 
 
 
The extension also introduces multiple functions for setting uniform values in a direct-state-access (DSA) style. This means that, in contrast to monolithic programs, one does not need to make a separate program the ''active'' program using {{apifunc|glUseProgram}} before modifying uniform values.
 
 
 
There are also several implications to consider when using separate programs, i.e. attribute bindings or interface block matching, which will be discussed in the following sections.
 
 
 
=== Creating a Separable Program ===
 
 
 
There are multiple ways of setting up a separable program. One is very convenient and does a lot of work in a single function call. The other takes more effort, but offers more flexibility.
 
 
 
==== The Single Shader Variant ====
 
In contrast to a monolithic program described above, much of the API calls to create, compile and link shader and programs have been wrapped into a single function: {{apifunc|glCreateShaderProgramv}}. It takes a shader type, e.g. {{enum|GL_VERTEX_SHADER}}, the number of source strings to be compiled and a pointer to an array of null-terminated source strings. Basically, calling this function is equivalent to
 
 
 
<source lang="cpp">
 
const GLuint shader = glCreateShader(type);
 
if (shader) {
 
    glShaderSource(shader, count, strings, NULL);
 
    glCompileShader(shader);
 
    const GLuint program = glCreateProgram();
 
    if (program) {
 
        GLint compiled = GL_FALSE;
 
        glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
 
        glProgramParameteri(program, GL_PROGRAM_SEPARABLE, GL_TRUE);
 
        if (compiled) {
 
            glAttachShader(program, shader);
 
            glLinkProgram(program);
 
            glDetachShader(program, shader);
 
        }
 
        /* append-shader-info-log-to-program-info-log */
 
    }
 
    glDeleteShader(shader);
 
    return program;
 
} else {
 
    return 0;
 
}
 
</source>
 
 
 
As can be seen, this is basically similar to creating a monolithic program. The is only one differences are that before linking the program, the implementation calls {{apifunc|glProgramParameter}} in the following way
 
 
 
  glProgramParameteri(''program'', {{enum|GL_PROGRAM_SEPARABLE}}, {{enum|GL_TRUE}});
 
 
 
and that the shader object is subsequently detached and deleted. The latter only affects relinking with {{apifunc|glLinkProgram}}, since no object code exists anymore after the shader has been detached. This will not impede the usability of the program in any other way. Technically, detaching and deleting is not necessary and could, if the program is setup manually as shown below, simply be left out.
 
 
 
{{note|{{apifunc|glCreateShaderProgramv}} will return either the name of a program object or zero - independent of which errors might occur during shader compilation or linkage! A return value of zero simply states that either the shader object or program object could be created. If a non-zero value is returned, you will still need to check the program info logs to make sure compilation and linkage succeeded! Also, the function itself my generate an error under certain conditions which will also result in zero being returned.}}
 
 
 
If the calls to {{apifunc|glCreateShader}} and {{apifunc|glCreateProgram}} succeed and both compilation and linkage succeed as well, the result is a program object consisting of a single executable for the specified shader stage.
 
 
 
==== Implications ====
 
 
 
Using {{apifunc|glCreateShaderProgramv}} has several implications to consider. First, since the operation is principally transparent, the developer cannot call certain functions before the program is linked. These include
 
 
 
* {{apifunc|glBindAttribLocation}}
 
* {{apifunc|glBindFragDataLocation}}
 
* {{apifunc|glBindFragDataLocationIndexed}}
 
 
 
The solution is to declare input and output locations ''explicitly'' inside a shader. For instance, binding an input variable in the vertex shader to a generic vertex attribute array can be replaced by adding the following line to the vertex shader:
 
 
 
  layout(location = 0) in vec4 input;
 
 
 
This way, there need not be a call to {{apifunc|glBindAttribLocation}} by the application. There may be similar additions to other shader stages.
 
 
 
==== The Multiple Shader Variant ====
 
 
 
Although it is very convenient, using {{apifunc|glCreateShaderProgramv}} is not necessary to setup a separable program. In fact, doing so imposes a limitation on the program: it can only contain executable code installable for a single shader stage. However, a separable program can actually contain multiple stages. In general, this requires to setup a monolithic program object and set the program parameter {{enum|GL_PROGRAM_SEPARABLE}} manually before linking.
 
 
 
==== Workaround for Location Binding ====
 
 
 
=== Setting up a Program Pipeline ===
 
 
 
Combining multiple, separable program objects is done by creating and setting up a program pipeline object. This is done by first letting the GL generate an appropriate name:
 
  
  GLuint pipeline;
+
{{funcdef|void {{apifunc|glUseProgram}}(GLuint {{param|program}});}}
  {{apifunc|glGenProgramPipelines}}(1, &pipeline);
 
  
To actually install a separable program in the pipeline one has to use {{apifunc|glUseProgramStages}}. For instance, installing a separate vertex shader program can be done like this:
+
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.
 
 
  GLuint pipeline, vShader;
 
  glGenProgramPipelines(1, &pipeline);
 
  vShader = glCreateShaderProgramv(GL_VERTEX_SHADER, ...);
 
  glUseProgramStages(pipeline, GL_VERTEX_SHADER_BIT, vShader);
 
  
If {{code|vShader}} was properly linked, this will install the shader program objects for the vertex shader stage of the program pipeline object {{code|pipeline}}.
+
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.
  
=== Rendering with a Program Pipeline ===
+
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.
  
Unlike monolithic programs, where one would use {{apifunc|glUseProgram}} in order to set the active shader program, here a call to {{apifunc|glBindProgramPipeline}} is needed. This will create an actual program pipeline object when a name generated by {{apifunc|glGenProgramPipelines}} is bound the first time. If it is called with another name for a program pipeline object, any previous bindings will be replaced. Calling it with zero will break any previous binding.
+
Then, bind the program pipeline object with:
  
{{apifunc|glBindProgramPipeline}} will have no effect if there is currently an active monolithic program activated with {{apifunc|glUseProgram}}. If in doubt, the safe way is to call the following sequence
+
{{funcdef|{{apifunc|glBindProgramPipeline}}(GLuint {{param|pipeline}});}}
  
  glUseProgram(0);
+
{{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.
  glBindProgramPipeline(pipeline);
 
  // ... call rendering commands afterwards
 
  
 
== Reference ==
 
== Reference ==
Line 272: Line 124:
 
* [[: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: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:

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