Compute Shaders
General-purpose GPU computation (GLSL 4.30+ / ES 3.10+ / Vulkan).
26.1 Execution model
Work is dispatched as a 3-D grid of workgroups (glDispatchCompute(x, y, z)).
Each workgroup has a fixed number of invocations (local_size_x/y/z, e.g., 8×8 or 256).
Invocations in a workgroup can share data through shared memory and synchronize with barrier().
index of the workgroup index within the workgroup gl_WorkGroupID * gl_WorkGroupSize + gl_LocalInvocationID flattened local index gl_NumWorkGroups, gl_WorkGroupSize dispatch and workgroup sizes
26.2 Image processing compute shader
#version 430 core
layout (local_size_x = 16, local_size_y = 16) in;
layout (rgba8, binding = 0) uniform readonly image2D uInput;
layout (rgba8, binding = 1) uniform writeonly image2D uOutput;
void main() {
ivec2 p = ivec2(gl_GlobalInvocationID.xy);
ivec2 size = imageSize(uInput);
if (p.x >= size.x || p.y >= size.y) return; // bounds check (dispatch rounds up)
vec4 c = imageLoad(uInput, p);
float g = dot(c.rgb, vec3(0.299, 0.587, 0.114));
imageStore(uOutput, p, vec4(vec3(g), c.a));
}glUseProgram(computeProg);
glBindImageTexture(0, inTex, 0, GL_FALSE, 0, GL_READ_ONLY, GL_RGBA8);
glBindImageTexture(1, outTex, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8);
glDispatchCompute((w + 15) / 16, (h + 15) / 16, 1);
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT | GL_TEXTURE_FETCH_BARRIER_BIT); // before using results26.3 Shared memory & barriers: parallel reduction
Synchronization functions: barrier() (workgroup execution + shared memory), memoryBarrierShared(), memoryBarrierBuffer(), memoryBarrierImage(), memoryBarrier(), groupMemoryBarrier().
#version 430 core
layout (local_size_x = 256) in;
layout (std430, binding = 0) readonly buffer In { float data[]; };
layout (std430, binding = 1) writeonly buffer Out { float partialSums[]; };
shared float sdata[256];
void main() {
uint tid = gl_LocalInvocationID.x;
uint gid = gl_GlobalInvocationID.x;
sdata[tid] = gid < uint(data.length()) ? data[gid] : 0.0;
barrier(); // execution barrier (also orders shared memory)
for (uint s = 128u; s > 0u; s >>= 1) {
if (tid < s) sdata[tid] += sdata[tid + s];
barrier();
}
if (tid == 0u) partialSums[gl_WorkGroupID.x] = sdata[0];
}26.4 Compute shader applications
GPU particle simulation, physics (cloth, fluids via SPH or grids), culling (frustum/occlusion → indirect draw commands), tiled/clustered light culling, histogram & auto-exposure, blur/bloom, FFT ocean simulation, skinning, procedural generation (terrain, noise textures), mipmap generation, ray tracing in software, image filters, machine-learning inference.
26.5 Indirect dispatch & draw
struct DrawCommand { uint count; uint instanceCount; uint firstIndex; int baseVertex; uint baseInstance; };
layout (std430, binding = 3) buffer Commands { DrawCommand cmds[]; };
// A culling compute shader fills cmds[] → glMultiDrawElementsIndirect draws only visible objects