Compute Shaders
The first sections of this chapter describe the graphics pipeline in OpenGL. However, OpenGL also includes the compute shader stage, which can almost be thought of as a separate pipeline that runs indepdendently of the other graphics-oriented stages.
Compute shaders are a way of getting at the computational power possessed by the graphics processor in the system. Unlike the graphics-centric vertex, tessellation, geometry, and fragment shaders, compute shaders could be considered as a special, single-stage pipeline all on their own. Each compute shader operates on a single unit of work known as a work item; these items are, in turn, collected together into small groups called local workgroups. Collections of these workgroups can be sent into OpenGL’s compute pipeline to be processed. The compute shader doesn’t have any fixed inputs or outputs besides a handful of built-in variables to tell the shader which item it is working on. All processing performed by a compute shader is explicitly written to memory by the shader itself, rather than being consumed by a subsequent pipeline stage. A very basic compute shader is shown in Listing 3.13.
Listing 3.13: Simple do-nothing compute shader
#version 450 core layout (local_size_x = 32, local_size_y = 32) in; void main(void) { // Do nothing }
Compute shaders are otherwise just like any other shader stage in OpenGL. To compile one, you create a shader object with the type GL_COMPUTE_SHADER, attach your GLSL source code to it with glShaderSource(), compile it with glCompileShader(), and then link it into a program with glAttachShader() and glLinkProgram(). The result is a program object with a compiled compute shader in it that can be launched to do work for you.
The shader in Listing 3.13 tells OpenGL that the size of the local workgroup will be 32 by 32 work items, but then proceeds to do nothing. To create a compute shader that actually does something useful, you need to know a bit more about OpenGL—so we’ll revisit this topic later in the book.