How EndStreamPrimitive Works in GLSL Streams
In OpenGL Shading Language (GLSL), EndStreamPrimitive is
a built-in geometry shader function used to finalize and complete the
current primitive on a designated output stream. When working with
geometry shaders that support multiple output streams—typically for
transform feedback—this function acts as a stream-specific delimiter. It
signals the GPU's primitive assembly stage that the sequence of vertices
previously emitted to that targeted stream is finished, allowing
subsequent emitted vertices on that stream to begin a new primitive.
Context of Multiple Output Streams
Modern geometry shaders can route generated vertices to multiple
output streams (from index 0 up to
gl_MaxVertexStreams - 1). Stream 0 can be routed either to
the rasterizer for rendering or captured via transform feedback, while
streams 1 and higher are strictly designated for transform feedback.
To manage independent topologies across these distinct pipelines,
GLSL replaces single-stream control functions (EmitVertex
and EndPrimitive) with their stream-aware equivalents:
EmitStreamVertex(int stream) and
EndStreamPrimitive(int stream).
Mechanism of Primitive Completion
When EndStreamPrimitive(int stream) is called, it
executes the following operations for the specified stream:
- Topology Termination: Geometry shaders typically
emit primitives using strip topologies, such as
triangle_striporline_strip.EndStreamPrimitivebreaks the current strip on the target stream. The next vertex pushed to this stream viaEmitStreamVertexwill not connect to the preceding vertices, starting a fresh strip instead. - Primitive Assembly Trigger: For closed topologies
like triangles or lines, the primitive assembler requires an explicit
signal to package the accumulated vertices into a complete primitive.
Calling
EndStreamPrimitiveconfirms that no more vertices will be appended to the current shape on that stream, allowing the GPU to pass the completed primitive down the pipeline. - Stream Isolation: The execution of
EndStreamPrimitiveon one stream operates independently of any other active streams. CallingEndStreamPrimitive(1)terminates the current primitive on stream 1 without affecting an in-progress primitive or strip being generated on stream 0.
Syntax and Implementation Requirements
The function signature is defined as:
void EndStreamPrimitive(int stream);To use EndStreamPrimitive correctly, several GLSL
constraints must be satisfied:
- Compile-Time Constant: The
streamparameter must be an integral constant expression known at compile time. It cannot be an index determined dynamically at runtime. - Valid Range: The stream index must lie within the
range
[0, gl_MaxVertexStreams - 1]. - Topology Restrictions on Higher Streams: Under the
core OpenGL specification, streams with an index greater than 0 must
output point primitives (
points). WhileEndStreamPrimitivecan still be invoked on these streams to maintain pipeline consistency, its functional necessity is most pronounced when breaking continuous strips on stream 0.
By invoking EndStreamPrimitive(stream), developers
maintain granular control over primitive boundaries across parallel
transform feedback buffers and the main rasterization path within a
single geometry shader invocation.