Using EmitStreamVertex in GLSL Geometry Shaders
In OpenGL Shading Language (GLSL), geometry shaders can separate and
direct generated primitives into multiple independent vertex streams for
transform feedback. This article explains how the built-in
EmitStreamVertex function operates, how it routes primitive
data to specific transform feedback streams, and the layout requirements
necessary to implement multiple output streams in geometry shaders.
The Role of EmitStreamVertex
The built-in function that routes primitive data to a specific
transform feedback stream is
EmitStreamVertex(int stream).
In standard single-stream pipelines, geometry shaders emit vertices
using EmitVertex(). However, when utilizing multiple
transform feedback streams (introduced in OpenGL 4.0 and the
ARB_gpu_shader5 extension), EmitStreamVertex
allows developers to explicitly assign an emitted vertex to a designated
stream index, ranging from 0 to
gl_MaxVertexStreams - 1.
Along with EmitStreamVertex(int stream), GLSL provides
EndStreamPrimitive(int stream) to signal the completion of
a primitive on that specific stream, matching the behavior of
EndPrimitive() in single-stream configurations.
Syntax and Layout Requirements
To use multiple streams, output variables in the geometry shader must
be bound to specific streams using the stream layout
qualifier. If an output variable does not specify a stream, it defaults
to stream 0.
#version 400 core
layout(triangles) in;
layout(points, max_vertices = 4) out;
// Assigning specific outputs to different streams
layout(stream = 0) out vec4 stream0_position;
layout(stream = 1) out vec3 stream1_normal;
void main() {
// Emit to Stream 0
stream0_position = gl_in[0].gl_Position;
EmitStreamVertex(0);
EndStreamPrimitive(0);
// Emit to Stream 1
stream1_normal = vec3(0.0, 1.0, 0.0);
EmitStreamVertex(1);
EndStreamPrimitive(1);
}Key Constraints
When routing data to specific transform feedback streams via
EmitStreamVertex, several pipeline limitations apply:
- Primitive Types: If any geometry shader output
stream uses an index greater than 0, the output primitive type for the
geometry shader must be declared as
points. - Rasterization: Only stream 0 can be passed down the standard rendering pipeline for rasterization. All other streams (1 and higher) are strictly used for transform feedback buffer capture.
- Stream Indexing: The
streamparameter inEmitStreamVertex(int stream)must be a compile-time constant expression. It cannot be dynamically indexed at runtime.