2.5. System Overview
We have already described briefly some of the pieces that provide applications with access to the programmability of underlying graphics hardware. This section briefly describes how these pieces go together in a working system.
2.5.1. Driver Model
A piece of software that controls a piece of hardware and manages shared access to that piece of hardware is commonly called a DRIVER. No matter what environment OpenGL is implemented in, it falls into the driver category because OpenGL manages shared access to the underlying graphics hardware. Some of its tasks must also be coordinated with, or supervised by, facilities in the operating system.
Figure 2.4 illustrates how OpenGL shaders are handled in the execution environment of OpenGL. Applications communicate with OpenGL by calling functions that are part of the OpenGL API. A new OpenGL function, glCreateShader, allows applications to allocate within the OpenGL driver the data structures that are necessary for storing an OpenGL shader. These data structures are called SHADER OBJECTS. After a shader object has been created, the application can provide the source code for the shader by calling glShaderSource. This command provides to OpenGL the character strings containing the shader source code.
Figure 2.4. Execution model for OpenGL shaders
As you can see from Figure 2.4, the compiler for the OpenGL Shading Language is actually part of the OpenGL driver environment. This is one of the key differences between the OpenGL Shading Language and other shading language designs, such as the Stanford Shading Language, High-Level Shader Language (HLSL) from Microsoft, or Cg from NVIDIA. In these other languages, the high-level shading language compiler sits above the graphics API and translates the high-level shading language into something that can be consumed by the underlying graphics API. (See Chapter 17 for more details.) With the OpenGL Shading Language, the source code for shaders is passed to the OpenGL driver, and in that environment, the shaders are compiled to the native machine code as efficiently as possible. After source code for a shader has been loaded into a shader object in the OpenGL driver environment, it can be compiled with glCompileShader.
A PROGRAM OBJECT is an OpenGL-managed data structure that acts as a container for shader objects. Applications are required to attach shader objects to a program object by using the command glAttachShader. When attached to a program object, the compiled shader objects can be linked with glLinkProgram. Support for multiple shader objects (and the subsequent need for a linker built into OpenGL) is a key difference between the OpenGL Shading Language and assembly-level APIs such as those provided by the OpenGL extensions ARB_vertex_program and ARB_fragment_program. For more complex shading tasks, separately compiled shader objects are a much more attractive alternative than a single, monolithic block of assembly-level code.
The link step resolves external references between the shaders, checks the compatibility between the vertex shader and the fragment shader, assigns memory locations to uniform variables, and so on. The result is one or more executables that can be installed with glUseProgram as part of OpenGL's current state. This command installs the executables on the vertex processor, the fragment processor, or both. The installed executables are responsible for processing all subsequent graphics primitives.
2.5.2. OpenGL Shading Language Compiler/Linker
The source for a single shader is an array of strings of characters, and a single shader is made from the concatenation of these strings. There is no inherent connection between strings and the lines of code in a shader. A shader may be entirely represented by a single string, or each line of shader source code may be contained in a separate string. Each string can contain multiple lines, separated by new-lines. No new-lines need be present in a string; a single line can be formed from multiple strings. No new-lines or other characters are inserted by the OpenGL implementation when it concatenates the strings to form a single shader. It is entirely up to the application programmer to provide shader source code to OpenGL with new-lines between each line of source code.
Diagnostic messages returned from compiling a shader must identify both the line number within a string and the source string to which the diagnostic message applies. Source strings are counted sequentially with the first string counted as string 0. For source code parsing, the current line number is one more than the number of new-lines that have been processed.
The front end of the OpenGL Shading Language compiler has been released as open source by 3Dlabs and can be used by anyone interested in writing his or her own compiler. This publicly available front end performs lexical analysis of OpenGL Shading Language source code to produce a token stream and then performs syntactic and semantic analysis of this token stream to produce a binary, high-level representation of the language. This front end acts as a reference implementation of the OpenGL Shading Language, and therefore it goes hand-in-hand with the language specification to define the language clearly. Another advantage to using this publicly available front end in an OpenGL Shading Language compiler implementation is that the syntax and semantics for shaders are checked consistently by all implementations that use this front end. More consistency among compiler implementations makes it easier for developers to write shaders that work as intended across a variety of implementations.
It is assumed that the back end of the OpenGL Shading Language compiler will be implemented differently on different platforms. Each implementation must take the high-level representation produced by the publicly available front end and produce optimized machine code for a particular hardware target. This is an area in which individual hardware vendors can add value to their shading language implementation by figuring out ways to map the high-level representation onto the actual machine instructions found in their hardware. Likewise, the linking stage is also highly hardware dependent because it involves operations like assigning variables to actual memory locations in the hardware. A variety of global optimizations may also be performed as part of linking.
The net result of this assumption is that graphics hardware vendors will implement the majority of the OpenGL Shading Language compiler and linker. Along with the OpenGL driver itself, this software will typically be included as part of the graphics driver installation package that is provided by a graphics hardware vendor.
2.5.3. OpenGL Shading Language API
As of OpenGL 2.0, support for the OpenGL Shading Language is available as part of standard OpenGL. The following OpenGL entry points support the OpenGL Shading Language
These new entry points are all discussed in more detail in Chapter 7. Reference pages for all of the OPENGL SHADING LANGUAGE API entry points defined by these extensions are included in Appendix B at the back of this book.