5. Shader Programs

Shader programs can customize the 3D graphics pipeline and control various graphics effects on the 3DS system.

There are three types of 3DS shader programs: one processes vertices, one creates geometry, and one processes fragments.

The shader program that processes vertices (the vertex shader) can be a unique shader programmed by developers.

The shader program that creates geometry (the geometry shader) is provided by the SDK. Geometry shaders and vertex shaders can be used in conjunction with each other.

The shader program that processes fragments (the fragment shader) is not programmable. Fragment processing is implemented as a fixed pipeline, but it can be controlled through reserved uniforms. This document uses the terms reserved fragment processing and reserved fragment shader to refer to the fragment pipeline and shader program, respectively.

5.1. Creating Shaders

Vertex shaders are the only shader programs that can be created by developers. The series of procedures related to vertex processing follow the OpenGL ES 2.0 specifications, but some features are not supported.

Shader programs are written in an assembly language that is unique to the PICA graphics core. For an application to use a shader program, it must load and then attach a binary generated by a special-purpose assembler and linker. The glShaderSource() and glCompileShader() functions in the OpenGL ES 2.0 specifications are not implemented.

For more information about how to create a vertex shader, see 8. Vertex Shader and the Vertex Shader Reference.

5.2. Loading Shaders

As explained in 5.1. Creating Shaders, you must load and then attach a shader program's binary data. Use the glCreateShader() function first to create a shader object.

Code 5-1. Definition of the glCreateShader Function
GLuint glCreateShader(GLenum type); 

The value to pass as type depends on the shader program being loaded. The reserved fragment shader uses a fixed implementation and does not need to be loaded.

Table 5-1. Shader Object Types

Type

Generated Object

GL_VERTEX_SHADER

A developer-created vertex shader object.

GL_GEOMETRY_SHADER_DMP

A geometry shader object provided by the SDK.

Load the shader program binary into memory and then bind it to the GPU with the glShaderBinary() function.

Code 5-2. Definition of the glShaderBinary Function
void glShaderBinary(GLint n, const GLuint* shaders, GLenum binaryformat, 
                    const void* binary, GLint length); 

For shaders, specify an array of shader objects, and for n, specify the number of array elements. Because you can only load a binary that was created by the assembler and linker, set binaryformat to GL_PLATFORM_BINARY_DMP. Set binary to the address at which the shader program binary was loaded and set length to the binary's size (in bytes).

The loaded shader programs are bound to the array in the order that they were passed to the linker. You can use the map file output by the linker to check the number of elements in the array and the type of shader objects to set. For more information, see the Vertex Shader Reference.

5.3. Attaching Shaders

To use a loaded shader program, an application must attach the shader program to a program object created by glCreateProgram, and then link that program object.

Code 5-3. Definition of the glCreateProgram Function
GLuint glCreateProgram(void); 

Unlike in OpenGL ES 2.0, program objects have a 13-bit namespace that is independent of shader objects. Consequently, up to 8191 objects can be created simultaneously. If any of these objects are deleted by glDeleteProgram, they can be re-created.

Use the glAttachShader() function to attach a shader program to a program object.

Code 5-4. Definition of the glAttachShader Function
void glAttachShader(GLuint program, GLuint shader); 

Set program to the return value from glCreateProgram() and set shader to the shader object.

Both the vertex shader and geometry shader are attached from loaded binaries. The reserved fragment shader, on the other hand, does not need to be loaded and is attached by setting shader to GL_DMP_FRAGMENT_SHADER_DMP.

You can attach one vertex shader, one geometry shader, and one reserved fragment shader to a single program object. In other words, if a point shader and line shader (both geometry shaders) are attached one after the other, only the line shader is activated.

Use the glLinkProgram() function to link a program object.

Code 5-5. Definition of the glLinkProgram Function
void glLinkProgram(GLuint program); 

You can link more than one program object. However, if you use glAttachShader to attach a different shader program to a linked program object, you must use glLinkProgram to relink the program object. The program object fails to be linked when the vertex shader and geometry shader use a total of more than 2048 uniforms.

5.4. Using Shaders

Call the glUseProgram() function to apply a linked shader program to the 3D processing pipeline.

Code 5-6. Definition of the glUseProgram Function
void glUseProgram(GLuint program); 

This function allows you to switch between several linked shader programs.

OpenGL allowed you to call the glValidateProgram() function to validate a shader program, but this function does nothing when it is called on a 3DS system.

Code 5-7. Definition of the glValidateProgram Function
void glValidateProgram(GLuint program); 

5.5. Detaching Shaders

You can use the glDetachShader() function to detach shader programs that are no longer necessary.

Code 5-8. Definition of the glDetachShader Function
void glDetachShader(GLuint program, GLuint shader); 

5.6. Destroying Shaders

You can use the glDeleteShader() function to destroy shader objects that are no longer necessary.

Code 5-9. Definition of the glDeleteShader Function
void glDeleteShader(GLuint shader); 

5.7. Querying Shaders

You can query program objects and shader objects to determine whether they are valid or invalid, and to get parameters and other shader-related information.

5.7.1. Validation

You can use the glIsProgram() and glIsShader() functions to determine whether program objects and shader objects are valid.

Code 5-10. Definition of the glIsProgram and glIsShader Functions
GLboolean glIsProgram(GLuint program);
GLboolean glIsShader(GLuint shader); 

These functions return a value of GL_TRUE if the program object or shader object passed as an argument is valid and GL_FALSE if it is not.

5.7.2. Getting Attached Shader Objects

You can use the glGetAttachedShaders() function to get the shader objects attached to a program object.

Code 5-11. Definition of the glGetAttachedShaders Function
void glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, 
                          GLuint* shaders); 

A list of shader objects attached to the program object specified by program is stored in the array specified by shaders. For maxcount, specify the size of the array specified in shaders. A GL_INVALID_VALUE error is generated if program is invalid or maxcount is negative.

The count parameter holds the number of shader objects that were saved. This value is not saved if NULL is specified, but you can get the number of attached shader objects by calling the glGetProgramiv() function (described later) with GL_ATTACHED_SHADERS passed as an argument.

5.7.3. Getting Command List Parameters

You can use the glGetProgramiv() and glGetShaderiv() functions to get parameters for program objects and shader objects.

Code 5-12. Definition of the glGetProgramiv and glGetShaderiv Functions
void glGetProgramiv(GLuint program, GLenum pname, GLint* params);
void glGetShaderiv(GLuint shader, GLenum pname, GLint* params); 

These functions store parameter values in params that correspond to the parameter name specified by pname. A GL_INVALID_ENUM error is generated if an invalid value is specified for pname. A GL_INVALID_VALUE error is generated if an invalid value is specified for program or shader.

The following table shows the parameter names that can be specified for pname and the parameters that are stored in params for the glGetProgramiv() function.

Table 5-2. Specifiable Parameter Names and Values Saved for the glGetProgramiv Function

pname

Values Saved in params

GL_DELETE_STATUS

GL_TRUE if the program object is in the "waiting to be deleted" state, and GL_FALSE otherwise. A program object in use by glUseProgram transitions to the "waiting to be deleted" state when glDeleteProgram is called on it.

GL_LINK_STATUS

GL_TRUE if glLinkProgram has successfully linked the program object, and GL_FALSE otherwise.

GL_VALIDATE_STATUS

The same value as when GL_LINK_STATUS is specified.

GL_INFO_LOG_LENGTH

Always 0.

GL_ATTACHED_SHADERS

The number of shader objects attached to the program object.

GL_ACTIVE_ATTRIBUTES

The number of vertex attributes in the active state.

GL_ACTIVE_ATTRIBUTE_MAX_LENGTH

The number of characters in the longest name of the active vertex attributes. The character count includes the terminating character (NULL).

GL_ACTIVE_UNIFORMS

The number of uniforms in the active state.

GL_ACTIVE_UNIFORM_MAX_LENGTH

The number of characters in the longest name of the active uniforms. The character count includes the terminating character (NULL).

The following table shows the parameter names that can be specified for pname, and the parameters that are stored in params for the glGetShaderiv() function.

Table 5-3. Specifiable Parameter Names and Values Saved for the glGetShaderiv Function

pname

Values Saved in params

GL_SHADER_TYPE

The shader type.

GL_DELETE_STATUS

GL_TRUE if the shader object is in the "waiting to be deleted" state, and GL_FALSE otherwise. The shader object attached to a program object transitions to the "waiting to be deleted" state when glDeleteShader is called on it.

GL_COMPILE_STATUS

Always GL_FALSE.

GL_INFO_LOG_LENGTH

Always 0.

GL_SHADER_SOURCE_LENGTH

Always 0.


CONFIDENTIAL