# Tessellation

Tessellation involves three pipeline stages. First, a tessellation control shader transforms control points of a patch and can produce per-patch data. Second, a fixed-function tessellator generates multiple primitives corresponding to a tessellation of the patch in (u,v) or (u,v,w) parameter space. Third, a tessellation evaluation shader transforms the vertices of the tessellated patch, for example to compute their positions and attributes as part of the tessellated surface. The tessellator is enabled when the pipeline contains both a tessellation control shader and a tessellation evaluation shader.

## Tessellator

If a pipeline includes both tessellation shaders (control and evaluation),
the tessellator consumes each input patch (after vertex shading) and
produces a new set of independent primitives (points, lines, or triangles).
These primitives are logically produced by subdividing a geometric primitive
(rectangle or triangle) according to the per-patch outer and inner
tessellation levels written by the tessellation control shader.
These levels are specified using the built-in
variables `TessLevelOuter`

and `TessLevelInner`

, respectively.
This subdivision is performed in an implementation-dependent manner.
If no tessellation shaders are present in the pipeline, the tessellator is
disabled and incoming primitives are passed through without modification.

The type of subdivision performed by the tessellator is specified by an
`OpExecutionMode`

instruction using one of the `Triangles`

,
`Quads`

, or `IsoLines`

execution modes.
When using shader objects, this instruction must be
specified in the tessellation evaluation shader, and may also be specified
in the tessellation control shader.
When using pipelines, this
instruction may be specified in either the tessellation evaluation or
tessellation control shader.
When using shader objects, tessellation-related modes that are requiredmust be specified in the tessellation evaluation shader, and may also be
specified in the tessellation control shader.
Other tessellation-related modes may be specified in the tessellation
evaluation shader.
When using pipelines, other
tessellation-related execution modes can also be specified in either the
tessellation control or tessellation evaluation shaders.

Any tessellation-related modes specified in both the tessellation control and tessellation evaluation shaders must be the same.

Tessellation execution modes include:

`Triangles`

,`Quads`

, and`IsoLines`

. These control the type of subdivision and topology of the output primitives. When using shader objects, one mode must be set in at least the tessellation evaluation stage. When using pipelines, one mode must be set in at least one of the tessellation shader stages. If the VK_KHR_portability_subset extension is enabled, and VkPhysicalDevicePortabilitySubsetFeaturesKHR::`tessellationIsolines`

is`VK_FALSE`

, then isoline tessellation is not supported by the implementation, and`IsoLines`

must not be used in either tessellation shader stage.`VertexOrderCw`

and`VertexOrderCcw`

. These control the orientation of triangles generated by the tessellator. When using shader objects, one mode must be set in at least the tessellation evaluation stage. When using pipelines, one mode must be set in at least one of the tessellation shader stages.`PointMode`

. Controls generation of points rather than triangles or lines. This functionality defaults to disabled, and is enabled if either shader stage includes the execution mode. When using shader objects, if`PointMode`

is set in the tessellation control stage, it must be identically set in the tessellation evaluation stage. If the VK_KHR_portability_subset extension is enabled, and VkPhysicalDevicePortabilitySubsetFeaturesKHR::`tessellationPointMode`

is`VK_FALSE`

, then point mode tessellation is not supported by the implementation, and`PointMode`

must not be used in either tessellation shader stage.`SpacingEqual`

,`SpacingFractionalEven`

, and`SpacingFractionalOdd`

. Controls the spacing of segments on the edges of tessellated primitives. When using shader objects, one mode must be set in at least the tessellation evaluation stage. When using pipelines, one mode must be set in at least one of the tessellation shader stages.`OutputVertices`

. Controls the size of the output patch of the tessellation control shader. When using shader objects, one value must be set in at least the tessellation control stage. When using pipelines, one value must be set in at least one of the tessellation shader stages.

For triangles, the tessellator subdivides a triangle primitive into smaller
triangles.
For quads, the tessellator subdivides a rectangle primitive into smaller
triangles.
For isolines, the tessellator subdivides a rectangle primitive into a
collection of line segments arranged in strips stretching across the
rectangle in the u dimension (i.e. the coordinates in `TessCoord`

are of the form (0,x) through (1,x) for all tessellation
evaluation shader invocations that share a line).

Each vertex produced by the tessellator has an associated (u,v,w) or (u,v)
position in a normalized parameter space, with parameter values in the range
[0,1], as illustrated
in figures xref::name::img-tessellation-topology-ul and
xref::name::img-tessellation-topology-ll.
The domain space can have either an upper-left or lower-left origin,
selected by the `domainOrigin`

member of
VkPipelineTessellationDomainOriginStateCreateInfo.

For triangles, the vertex’s position is a barycentric coordinate (u,v,w), where u + v + w = 1.0, and indicates the relative influence of the three vertices of the triangle on the position of the vertex. For quads and isolines, the position is a (u,v) coordinate indicating the relative horizontal and vertical position of the vertex relative to the subdivided rectangle. The subdivision process is explained in more detail in subsequent sections.

## Tessellator Patch Discard

A patch is discarded by the tessellator if any relevant outer tessellation level is less than or equal to zero.

Patches will also be discarded if any relevant outer tessellation level corresponds to a floating-point NaN (not a number) in implementations supporting NaN.

No new primitives are generated and the tessellation evaluation shader is
not executed for patches that are discarded.
For `Quads`

, all four outer levels are relevant.
For `Triangles`

and `IsoLines`

, only the first three or two outer
levels, respectively, are relevant.
Negative inner levels will not cause a patch to be discarded; they will be
clamped as described below.

## Tessellator Spacing

Each of the tessellation levels is used to determine the number and spacing
of segments used to subdivide a corresponding edge.
The method used to derive the number and spacing of segments is specified by
an `OpExecutionMode`

in the tessellation control or tessellation
evaluation shader using one of the identifiers `SpacingEqual`

,
`SpacingFractionalEven`

, or `SpacingFractionalOdd`

.

If `SpacingEqual`

is used, the floating-point tessellation level is first
clamped to [1, `maxLevel`

], where `maxLevel`

is the
implementation-dependent maximum tessellation level
(`VkPhysicalDeviceLimits`

::`maxTessellationGenerationLevel`

).
The result is rounded up to the nearest integer n, and the
corresponding edge is divided into n segments of equal length in (u,v)
space.

If `SpacingFractionalEven`

is used, the tessellation level is first
clamped to [2, `maxLevel`

] and then rounded up to the nearest even
integer n.
If `SpacingFractionalOdd`

is used, the tessellation level is clamped to
[1, `maxLevel`

- 1] and then rounded up to the nearest odd integer
n.
If n is one, the edge will not be subdivided.
Otherwise, the corresponding edge will be divided into n - 2 segments
of equal length, and two additional segments of equal length that are
typically shorter than the other segments.
The length of the two additional segments relative to the others will
decrease monotonically with n - f, where f is the clamped
floating-point tessellation level.
When n - f is zero, the additional segments will have equal length to
the other segments.
As n - f approaches 2.0, the relative length of the additional
segments approaches zero.
The two additional segments must be placed symmetrically on opposite sides
of the subdivided edge.
The relative location of these two segments is implementation-dependent, but
must be identical for any pair of subdivided edges with identical values of
f.

When tessellating triangles or quads using point
mode with fractional odd spacing, the tessellator may produce *interior
vertices* that are positioned on the edge of the patch if an inner
tessellation level is less than or equal to one.
Such vertices are considered distinct from vertices produced by subdividing
the outer edge of the patch, even if there are pairs of vertices with
identical coordinates.

## Tessellation Primitive Ordering

Few guarantees are provided for the relative ordering of primitives produced by tessellation, as they pertain to primitive order.

- The output primitives generated from each input primitive are passed to subsequent pipeline stages in an implementation-dependent order.
- All output primitives generated from a given input primitive are passed to subsequent pipeline stages before any output primitives generated from subsequent input primitives.

## Tessellator Vertex Winding Order

When the tessellator produces triangles (in the `Triangles`

or `Quads`

modes), the orientation of all triangles is specified with an
`OpExecutionMode`

of `VertexOrderCw`

or `VertexOrderCcw`

in the
tessellation control or tessellation evaluation shaders.
If the order is `VertexOrderCw`

, the vertices of all generated triangles
will have clockwise ordering in (u,v) or (u,v,w) space.
If the order is `VertexOrderCcw`

, the vertices will have
counter-clockwise ordering in that space.

If the tessellation domain has an upper-left origin, the vertices of a triangle have counter-clockwise ordering if

- a = u
_{0}v_{1}- u_{1}v_{0}+ u_{1}v_{2}- u_{2}v_{1}+ u_{2}v_{0}- u_{0}v_{2}

is negative, and clockwise ordering if a is positive.
u_{i} and v_{i} are the u and v coordinates in
normalized parameter space of the ith vertex of the triangle.
If the tessellation domain has a lower-left origin, the vertices of a
triangle have counter-clockwise ordering if a is positive, and
clockwise ordering if a is negative.

The value a is proportional (with a positive factor) to the signed area of the triangle.

In `Triangles`

mode, even though the vertex coordinates have a w
value, it does not participate directly in the computation of a, being
an affine combination of u and v.

## Triangle Tessellation

If the tessellation primitive mode is `Triangles`

, an equilateral
triangle is subdivided into a collection of triangles covering the area of
the original triangle.
First, the original triangle is subdivided into a collection of concentric
equilateral triangles.
The edges of each of these triangles are subdivided, and the area between
each triangle pair is filled by triangles produced by joining the vertices
on the subdivided edges.
The number of concentric triangles and the number of subdivisions along each
triangle except the outermost is derived from the first inner tessellation
level.
The edges of the outermost triangle are subdivided independently, using the
first, second, and third outer tessellation levels to control the number of
subdivisions of the u = 0 (left), v = 0 (bottom), and w =
0 (right) edges, respectively.
The second inner tessellation level and the fourth outer tessellation level
have no effect in this mode.

If the first inner tessellation level and all three outer tessellation
levels are exactly one after clamping and rounding, only a single triangle
with (u,v,w) coordinates of (0,0,1), (1,0,0), and
(0,1,0) is generated.
If the inner tessellation level is one and any of the outer tessellation
levels is greater than one, the inner tessellation level is treated as
though it were originally specified as 1 + ε and will
result in a two- or three-segment subdivision depending on the tessellation
spacing.
When used with fractional odd spacing, the three-segment subdivision may
produce *inner vertices* positioned on the edge of the triangle.

If any tessellation level is greater than one, tessellation begins by producing a set of concentric inner triangles and subdividing their edges. First, the three outer edges are temporarily subdivided using the clamped and rounded first inner tessellation level and the specified tessellation spacing, generating n segments. For the outermost inner triangle, the inner triangle is degenerate — a single point at the center of the triangle — if n is two. Otherwise, for each corner of the outer triangle, an inner triangle corner is produced at the intersection of two lines extended perpendicular to the corner’s two adjacent edges running through the vertex of the subdivided outer edge nearest that corner. If n is three, the edges of the inner triangle are not subdivided and it is the final triangle in the set of concentric triangles. Otherwise, each edge of the inner triangle is divided into n - 2 segments, with the n - 1 vertices of this subdivision produced by intersecting the inner edge with lines perpendicular to the edge running through the n - 1 innermost vertices of the subdivision of the outer edge. Once the outermost inner triangle is subdivided, the previous subdivision process repeats itself, using the generated triangle as an outer triangle. This subdivision process is illustrated in Inner Triangle Tessellation.

Once all the concentric triangles are produced and their edges are subdivided, the area between each pair of adjacent inner triangles is filled completely with a set of non-overlapping triangles. In this subdivision, two of the three vertices of each triangle are taken from adjacent vertices on a subdivided edge of one triangle; the third is one of the vertices on the corresponding edge of the other triangle. If the innermost triangle is degenerate (i.e., a point), the triangle containing it is subdivided into six triangles by connecting each of the six vertices on that triangle with the center point. If the innermost triangle is not degenerate, that triangle is added to the set of generated triangles as-is.

After the area corresponding to any inner triangles is filled, the tessellator generates triangles to cover the area between the outermost triangle and the outermost inner triangle. To do this, the temporary subdivision of the outer triangle edge above is discarded. Instead, the u = 0, v = 0, and w = 0 edges are subdivided according to the first, second, and third outer tessellation levels, respectively, and the tessellation spacing. The original subdivision of the first inner triangle is retained. The area between the outer and first inner triangles is completely filled by non-overlapping triangles as described above. If the first (and only) inner triangle is degenerate, a set of triangles is produced by connecting each vertex on the outer triangle edges with the center point.

After all triangles are generated, each vertex in the subdivided triangle is assigned a barycentric (u,v,w) coordinate based on its location relative to the three vertices of the outer triangle.

The algorithm used to subdivide the triangular domain in (u,v,w) space into individual triangles is implementation-dependent. However, the set of triangles produced will completely cover the domain, and no portion of the domain will be covered by multiple triangles.

Output triangles are generated with a topology similar to triangle lists, except that the order in which each triangle is generated, and the order in which the vertices are generated for each triangle, are implementation-dependent. However, the order of vertices in each triangle is consistent across the domain as described in Tessellator Vertex Winding Order.

## Quad Tessellation

If the tessellation primitive mode is `Quads`

, a rectangle is subdivided
into a collection of triangles covering the area of the original rectangle.
First, the original rectangle is subdivided into a regular mesh of
rectangles, where the number of rectangles along the u = 0 and u
= 1 (vertical) and v = 0 and v = 1 (horizontal) edges are
derived from the first and second inner tessellation levels, respectively.
All rectangles, except those adjacent to one of the outer rectangle edges,
are decomposed into triangle pairs.
The outermost rectangle edges are subdivided independently, using the first,
second, third, and fourth outer tessellation levels to control the number of
subdivisions of the u = 0 (left), v = 0 (bottom), u = 1
(right), and v = 1 (top) edges, respectively.
The area between the inner rectangles of the mesh and the outer rectangle
edges are filled by triangles produced by joining the vertices on the
subdivided outer edges to the vertices on the edge of the inner rectangle
mesh.

If both clamped inner tessellation levels and all four clamped outer
tessellation levels are exactly one, only a single triangle pair covering
the outer rectangle is generated.
Otherwise, if either clamped inner tessellation level is one, that
tessellation level is treated as though it was originally specified as
1 + ε and will result in a two- or three-segment
subdivision depending on the tessellation spacing.
When used with fractional odd spacing, the three-segment subdivision may
produce *inner vertices* positioned on the edge of the rectangle.

If any tessellation level is greater than one, tessellation begins by
subdividing the u = 0 and u = 1 edges of the outer rectangle
into m segments using the clamped and rounded first inner tessellation
level and the tessellation spacing.
The v = 0 and v = 1 edges are subdivided into n segments
using the second inner tessellation level.
Each vertex on the u = 0 and v = 0 edges are joined with the
corresponding vertex on the u = 1 and v = 1 edges to produce a
set of vertical and horizontal lines that divide the rectangle into a grid
of smaller rectangles.
The primitive generator emits a pair of non-overlapping triangles covering
each such rectangle not adjacent to an edge of the outer rectangle.
The boundary of the region covered by these triangles forms an inner
rectangle, the edges of which are subdivided by the grid vertices that lie
on the edge.
If either m or n is two, the inner rectangle is degenerate, and
one or both of the rectangle’s *edges* consist of a single point.
This subdivision is illustrated in Figure Inner Quad
Tessellation.

After the area corresponding to the inner rectangle is filled, the
tessellator must produce triangles to cover the area between the inner and
outer rectangles.
To do this, the subdivision of the outer rectangle edge above is discarded.
Instead, the u = 0, v = 0, u = 1, and v = 1 edges
are subdivided according to the first, second, third, and fourth outer
tessellation levels, respectively, and the tessellation spacing.
The original subdivision of the inner rectangle is retained.
The area between the outer and inner rectangles is completely filled by
non-overlapping triangles.
Two of the three vertices of each triangle are adjacent vertices on a
subdivided edge of one rectangle; the third is one of the vertices on the
corresponding edge of the other rectangle.
If either edge of the innermost rectangle is degenerate, the area near the
corresponding outer edges is filled by connecting each vertex on the outer
edge with the single vertex making up the *inner edge*.

The algorithm used to subdivide the rectangular domain in (u,v) space into individual triangles is implementation-dependent. However, the set of triangles produced will completely cover the domain, and no portion of the domain will be covered by multiple triangles.

Output triangles are generated with a topology similar to triangle lists, except that the order in which each triangle is generated, and the order in which the vertices are generated for each triangle, are implementation-dependent. However, the order of vertices in each triangle is consistent across the domain as described in Tessellator Vertex Winding Order.

## Isoline Tessellation

If the tessellation primitive mode is `IsoLines`

, a set of independent
horizontal line segments is drawn.
The segments are arranged into connected strips called *isolines*, where the
vertices of each isoline have a constant v coordinate and u coordinates
covering the full range [0,1].
The number of isolines generated is derived from the first outer
tessellation level; the number of segments in each isoline is derived from
the second outer tessellation level.
Both inner tessellation levels and the third and fourth outer tessellation
levels have no effect in this mode.

As with quad tessellation above, isoline tessellation begins with a rectangle. The u = 0 and u = 1 edges of the rectangle are subdivided according to the first outer tessellation level. For the purposes of this subdivision, the tessellation spacing mode is ignored and treated as equal_spacing. An isoline is drawn connecting each vertex on the u = 0 rectangle edge to the corresponding vertex on the u = 1 rectangle edge, except that no line is drawn between (0,1) and (1,1). If the number of isolines on the subdivided u = 0 and u = 1 edges is n, this process will result in n equally spaced lines with constant v coordinates of 0, $\frac{1}{n}, \frac{2}{n}, \ldots, \frac{n-1}{n}$.

Each of the n isolines is then subdivided according to the second outer tessellation level and the tessellation spacing, resulting in m line segments. Each segment of each line is emitted by the tessellator. These line segments are generated with a topology similar to line lists, except that the order in which each line is generated, and the order in which the vertices are generated for each line segment, are implementation-dependent.

If the VK_KHR_portability_subset extension is enabled, and
VkPhysicalDevicePortabilitySubsetFeaturesKHR::`tessellationIsolines`

is `VK_FALSE`

, then isoline tessellation is not supported by the
implementation.

## Tessellation Point Mode

For all primitive modes, the tessellator is capable of generating points
instead of lines or triangles.
If the tessellation control or tessellation evaluation shader specifies the
`OpExecutionMode`

`PointMode`

, the primitive generator will generate
one point for each distinct vertex produced by tessellation, rather than
emitting triangles or lines.
Otherwise, the tessellator will produce a collection of line segments or
triangles according to the primitive mode.
These points are generated with a topology similar to point lists, except the order in which the points are generated for each
input primitive is undefined:.

If the VK_KHR_portability_subset extension is enabled, and
VkPhysicalDevicePortabilitySubsetFeaturesKHR::`tessellationPointMode`

is `VK_FALSE`

, then tessellation point mode is not supported by the
implementation.

## Tessellation Pipeline State

The `pTessellationState`

member of VkGraphicsPipelineCreateInfo is
a pointer to a `VkPipelineTessellationStateCreateInfo`

structure.