Understanding gl_PatchVerticesIn in GLSL
This article provides an overview of the built-in GLSL variable
gl_PatchVerticesIn, explaining how it communicates the
number of control points per input patch to tessellation shaders. You
will learn how this value is established on the CPU via OpenGL commands,
how it dictates the sizing of input arrays in both the Tessellation
Control Shader (TCS) and Tessellation Evaluation Shader (TES), and how
to use it effectively in your rendering pipeline.
What is gl_PatchVerticesIn?
In the OpenGL pipeline, tessellation processes geometric primitives
called patches. The built-in variable gl_PatchVerticesIn is
an implicitly declared integer (in int gl_PatchVerticesIn;)
available in tessellation shaders. It represents the number of
vertices—or control points—present in the input patch currently being
processed by the shader.
Behavior in the Tessellation Control Shader (TCS)
In the Tessellation Control Shader, gl_PatchVerticesIn
corresponds directly to the patch size configured by the host
application on the CPU. The OpenGL application sets this size using the
following state call:
glPatchParameteri(GL_PATCH_VERTICES, numVertices);When the draw call executes, gl_PatchVerticesIn in the
TCS reflects numVertices. It also specifies the implicit
dimension of the built-in input array gl_in[], as well as
any user-defined input arrays passed from the vertex shader. For
instance, if GL_PATCH_VERTICES is set to 4,
gl_PatchVerticesIn will evaluate to 4, indicating that
indices gl_in[0] through gl_in[3] contain
valid control point data.
Behavior in the Tessellation Evaluation Shader (TES)
The behavior of gl_PatchVerticesIn changes slightly in
the Tessellation Evaluation Shader depending on whether a TCS is
present:
When a TCS is present:
gl_PatchVerticesInin the TES reflects the output patch size defined by the TCS, not the initial size passed from the host. This count matches the layout qualifier defined in the TCS:layout(vertices = N) out;In this scenario,
gl_PatchVerticesInin the TES will equalN.When a TCS is omitted: The pipeline routes the original patch data directly to the TES. Here,
gl_PatchVerticesIndefaults back to the size configured byglPatchParameteri(GL_PATCH_VERTICES, ...).
Practical Usage
gl_PatchVerticesIn is commonly used as a loop bound when
inspecting, modifying, or passing through control point attributes.
Instead of hardcoding iteration limits, shaders can use this variable to
write flexible control code:
#version 450 core
layout(vertices = 3) out;
void main() {
// Pass attributes dynamically based on the input patch size
for (int i = 0; i < gl_PatchVerticesIn; ++i) {
// Process or inspect gl_in[i]
}
gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
// Set tessellation levels once per patch
if (gl_InvocationID == 0) {
gl_TessLevelInner[0] = 3.0;
gl_TessLevelOuter[0] = 3.0;
gl_TessLevelOuter[1] = 3.0;
gl_TessLevelOuter[2] = 3.0;
}
}By querying gl_PatchVerticesIn, tessellation stages
remain decoupled from fixed vertex counts, preventing out-of-bounds
array reads and ensuring correct correspondence between host setup and
GPU execution.