GLSL 4.00 Tessellation Shader Additions

The OpenGL Shading Language (GLSL) 4.00 specification introduced native hardware tessellation by adding two programmable stages—the Tessellation Control Shader (TCS) and the Tessellation Evaluation Shader (TES)—into the core rendering pipeline. This update defined dedicated input and output layout qualifiers, specialized built-in variables for controlling tessellation levels and reading generated coordinates, the patch storage qualifier for per-patch data, and execution synchronization primitives. Together, these additions allowed developers to dynamically generate and manipulate geometry directly on the GPU.

Two New Programmable Shader Stages

GLSL 4.00 divided tessellation across a fixed-function primitive generator flanked by two programmable shader stages:

  • Tessellation Control Shader (TCS): Positioned immediately after the vertex shader, the TCS determines the amount of tessellation to apply to an input patch by setting tessellation level factors. It can also transform or alter patch vertex attributes.
  • Tessellation Evaluation Shader (TES): Executed after the fixed-function tessellation generator, the TES takes the abstract coordinates produced by the generator along with the control points and computes final vertex positions and attributes for the subdivided geometry.

Patch Layout Qualifiers

GLSL 4.00 added specific layout qualifiers to configure how patches are consumed and subdivided:

  • TCS Output Layout: The TCS defines the number of vertices in the output patch using the vertices layout qualifier (e.g., layout(vertices = 16) out;).
  • TES Primitive Modes: The TES specifies the domain space using primitive generation qualifiers: triangles, quads, or isolines.
  • Subdivision and Spacing Modes: The TES controls how edge divisions are distributed via spacing qualifiers: equal_spacing, fractional_even_spacing, or fractional_odd_spacing.
  • Vertex Ordering and Display: Modifiers such as cw (clockwise) and ccw (counter-clockwise) define primitive winding order, while point_mode directs the pipeline to render the tessellated output as points rather than filled primitives.

Built-in Tessellation Variables

GLSL 4.00 introduced an array of built-in variables to pass and access data throughout the tessellation stages:

  • gl_TessLevelOuter and gl_TessLevelInner: Output float arrays in the TCS (and readable inputs in the TES) that define the outer edge and inner tessellation factors driving the primitive generator.
  • gl_TessCoord: A vec3 available exclusively in the TES that provides the barycentric coordinates (for triangles) or UV coordinates (for quads and isolines) of the vertex being generated.
  • gl_InvocationID: A TCS input identifying the specific output patch vertex being processed by the current shader invocation.
  • gl_PatchVerticesIn: Available in both TCS and TES, indicating the vertex count of the input patch.
  • gl_in[] and gl_out[]: Aggregated interface blocks allowing arrayed access to standard built-ins (such as gl_Position and gl_PointSize) across all control points in a patch.

The patch Storage Qualifier

To differentiate between per-vertex attributes and patch-wide metadata, GLSL 4.00 introduced the patch storage qualifier. Declaring a variable as patch out in a TCS or patch in in a TES ensures that the attribute is shared across the entire patch rather than duplicated per control point.

Execution Synchronization with barrier()

Because control shader invocations run concurrently per patch vertex, GLSL 4.00 added the built-in barrier() function. Calling barrier() inside a TCS halts execution until all invocations for that patch reach the barrier, preventing race conditions when reading outputs or per-patch variables written by neighboring invocations.