// Copyright (c) 2018-2020 NVIDIA Corporation
//
// SPDX-License-Identifier: CC-BY-4.0

[[mesh]]
= Mesh Shading

<<shaders-task,Task>> and <<shaders-mesh,mesh shaders>> operate in
workgroups to produce a collection of primitives that will be processed by
subsequent stages of the graphics pipeline.

Work on the mesh pipeline is initiated by the application
<<drawing-mesh-shading,drawing>> a set of mesh tasks organized in global
workgroups.
If the optional task shader is active, each workgroup triggers the execution
of task shader invocations that will create a new set of mesh workgroups
upon completion.
Each of these created workgroups, or each of the original workgroups if no
task shader is present, triggers the execution of mesh shader invocations.

Each mesh shader workgroup emits zero or more output primitives along with
the group of vertices and their associated data required for each output
primitive.


[[mesh-task-input]]
== Task Shader Input
For every workgroup issued via the drawing commands a group of task shader
invocations is executed.
There are no inputs other than the builtin workgroup identifiers.


[[mesh-task-output]]
== Task Shader Output
The task shader can emit zero or more mesh workgroups to be generated.
ifdef::VK_NV_mesh_shader[]
Shaders using the code:TaskNV {ExecutionModel} can do so using the
<<interfaces-builtin-variables,built-in variable>> code:TaskCountNV.
This value must: be less than or equal to
sname:VkPhysicalDeviceMeshShaderPropertiesNV::pname:maxTaskOutputCount.
endif::VK_NV_mesh_shader[]
ifdef::VK_EXT_mesh_shader[]
Shaders using the code:TaskEXT {ExecutionModel} can do so using the
code:OpEmitMeshTasksEXT instruction.
The code:groupCountX, code:groupCountY and code:groupCountZ arguments passed
to this instruction must: be less than or equal to the respective dimension
within
sname:VkPhysicalDeviceMeshShaderPropertiesEXT::pname:maxMeshWorkGroupCount.
The product of these arguments must: be less than or equal to
sname:VkPhysicalDeviceMeshShaderPropertiesEXT::pname:maxMeshWorkGroupTotalCount.
endif::VK_EXT_mesh_shader[]

The task shader can also pass user-defined data to all mesh shader
invocations that it creates.
ifdef::VK_NV_mesh_shader[]
Shaders using the code:TaskNV {ExecutionModel} can do so by writing to
output variables that are decorated with code:PerTaskNV.
They are available as inputs in mesh shaders.
endif::VK_NV_mesh_shader[]
ifdef::VK_EXT_mesh_shader[]
Shaders using the code:TaskEXT {ExecutionModel} can do so by writing to a
payload variable with code:TaskPayloadWorkgroupEXT storage class that is
passed to the code:OpEmitMeshTasksEXT instruction.
endif::VK_EXT_mesh_shader[]


[[mesh-generation]]
== Mesh Generation
If a task shader exists, the mesh assembler creates a variable amount of
mesh workgroups depending on each task's output.
If there is no task shader, the drawing commands emit the mesh shader
invocations directly.


[[mesh-input]]
== Mesh Shader Input
The only inputs available to the mesh shader are variables identifying the
specific workgroup and invocation and, if applicable,
ifdef::VK_NV_mesh_shader[]
any outputs written as code:PerTaskNV
endif::VK_NV_mesh_shader[]
ifdef::VK_NV_mesh_shader+VK_EXT_mesh_shader[or]
ifdef::VK_EXT_mesh_shader[]
the payload variable passed to the code:OpEmitMeshTasksEXT instruction
endif::VK_EXT_mesh_shader[]
by the task shader that spawned the mesh shader's workgroup.
The mesh shader can operate without a task shader as well.


[[mesh-output]]
== Mesh Shader Output

A mesh shader generates primitives in one of three output modes: points,
lines, or triangles.
ifdef::VK_NV_mesh_shader[]
For shaders using the code:MeshNV {ExecutionModel} the primitive mode is
specified in the shader using an code:OpExecutionMode instruction with the
code:OutputPoints, code:OutputLinesNV, or code:OutputTrianglesNV modes,
respectively.
endif::VK_NV_mesh_shader[]
ifdef::VK_EXT_mesh_shader[]
For shaders using the code:MeshEXT {ExecutionModel} the primitive mode is
specified in the shader using an code:OpExecutionMode instruction with the
code:OutputPoints, code:OutputLinesEXT, or code:OutputTrianglesEXT modes,
respectively.
endif::VK_EXT_mesh_shader[]
Each mesh shader must: include exactly one output primitive mode.

ifdef::VK_NV_mesh_shader[]
For shaders using the code:MeshNV {ExecutionModel} the maximum output vertex
count is specified as a literal in the shader using an code:OpExecutionMode
instruction with the mode set to code:OutputVertices and must: be less than
or equal to
sname:VkPhysicalDeviceMeshShaderPropertiesNV::pname:maxMeshOutputVertices.
endif::VK_NV_mesh_shader[]
ifdef::VK_EXT_mesh_shader[]
For shaders using the code:MeshEXT {ExecutionModel} the maximum output
vertex count is specified as a literal in the shader using an
code:OpExecutionMode instruction with the mode set to code:OutputVertices
and must: be less than or equal to
sname:VkPhysicalDeviceMeshShaderPropertiesEXT::pname:maxMeshOutputVertices.
endif::VK_EXT_mesh_shader[]

ifdef::VK_NV_mesh_shader[]
For shaders using the code:MeshNV {ExecutionModel} the maximum output
primitive count is specified as a literal in the shader using an
code:OpExecutionMode instruction with the mode set to
code:OutputPrimitivesNV and must: be less than or equal to
sname:VkPhysicalDeviceMeshShaderPropertiesNV::pname:maxMeshOutputPrimitives.
endif::VK_NV_mesh_shader[]
ifdef::VK_EXT_mesh_shader[]
For shaders using the code:MeshEXT {ExecutionModel} the maximum output
primitive count is specified as a literal in the shader using an
code:OpExecutionMode instruction with the mode set to
code:OutputPrimitivesEXT, and must: be less than or equal to
sname:VkPhysicalDeviceMeshShaderPropertiesEXT::pname:maxMeshOutputPrimitives.
endif::VK_EXT_mesh_shader[]

ifdef::VK_NV_mesh_shader[]
For shaders using the code:MeshNV {ExecutionModel} the number of primitives
output by the mesh shader is provided via writing to the
<<interfaces-builtin-variables,built-in variable>> code:PrimitiveCountNV and
must: be less than or equal to the maximum output primitive count specified
in the shader.
A variable decorated with code:PrimitiveIndicesNV is an output array of
local index values into the vertex output arrays from which primitives are
assembled according to the output primitive type.
endif::VK_NV_mesh_shader[]
ifdef::VK_EXT_mesh_shader[]
For shaders using the code:MeshEXT {ExecutionModel} the number of vertices
and primitives output by the mesh shader is provided via calling the
code:OpSetMeshOutputsEXT instruction.
The code:vertexCount argument must: be less than or equal to the maximum
output vertex count specified in the shader.
The code:primitiveCount argument must: be less than or equal to the maximum
output primitive count specified in the shader.

Depending on the output primitive mode an appropriately-decorated variable
is the output array of local index values into the vertex output arrays from
which primitives are assembled according to the output primitive type:

  * code:OutputPoints uses the code:PrimitivePointIndicesEXT decoration.
  * code:OutputLinesEXT uses the code:PrimitiveLineIndicesEXT decoration.
  * code:OutputTrianglesEXT uses the code:PrimitiveTriangleIndicesEXT
    decoration.
endif::VK_EXT_mesh_shader[]

These resulting primitives are then further processed as described in
<<primsrast>>.

ifdef::VK_EXT_mesh_shader[]
With the exception of primitive indices, all output built-ins and custom
attributes count towards the total storage size occupied by output variables
in mesh shaders.
This size can be calculated as follows, taking into account the fact that
the number of effective scalar attributes is 4 times the number of effective
locations used according to the <<interfaces-iointerfaces-locations,location
assignment rules>>.
Let latexmath:[v] be the number of views, latexmath:[n_v] be the number of
effective scalar per-vertex attributes not dependent on code:ViewIndex,
latexmath:[n_{vpv}] be the number of effective scalar per-vertex attributes
dependent on code:ViewIndex, latexmath:[m_v] be the maximum number of
vertices specified by the code:OutputVertices {ExecutionMode},
latexmath:[g_v] be pname:meshOutputPerVertexGranularity, latexmath:[n_p] be
the number of effective scalar per-primitive attributes not dependent on
code:ViewIndex, latexmath:[n_{ppv}] be the number of effective scalar
per-primitive attributes dependent on code:ViewIndex, latexmath:[m_p] be the
maximum number of primitives specified by the code:OutputPrimitivesEXT
{ExecutionMode} and latexmath:[g_p] be
pname:meshOutputPerPrimitiveGranularity:

[latexmath]
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
(n_v + (n_{vpv} \times v)) \times 4 \times \mathrm{align}(m_v, g_v) +
(n_p + (n_{ppv} \times v)) \times 4 \times \mathrm{align}(m_p, g_p)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

endif::VK_EXT_mesh_shader[]

ifdef::VK_NV_mesh_shader[]
[[mesh-output-perview]]
== Mesh Shader Per-View Outputs

The mesh shader outputs decorated with the code:PositionPerViewNV,
code:ClipDistancePerViewNV, code:CullDistancePerViewNV, code:LayerPerViewNV,
and code:ViewportMaskPerViewNV built-in decorations are the per-view
versions of the single-view variables with equivalent names (that is
code:Position, code:ClipDistance, code:CullDistance, code:Layer, and
code:ViewportMaskNV, respectively).
If a shader statically assigns a value to any element of a per-view array it
must: not statically assign a value to the equivalent single-view variable.

Each of these outputs is considered arrayed, with separate values for each
view.
The view number is used to index the first dimension of these arrays.

The second dimension of the code:ClipDistancePerViewNV, and
code:CullDistancePerViewNV arrays have the same requirements as the
code:ClipDistance, and code:CullDistance arrays.

If a mesh shader output is _per-view_, the corresponding fragment shader
input is taken from the element of the per-view output array that
corresponds to the view that is currently being processed by the fragment
shader.

ifdef::VK_EXT_mesh_shader[]
These _per-view_ outputs are available only in shaders using the code:MeshNV
{ExecutionModel}.
They are not available in shaders using the code:MeshEXT {ExecutionModel}.
endif::VK_EXT_mesh_shader[]

endif::VK_NV_mesh_shader[]


[[mesh-ordering]]
== Mesh Shader Primitive Ordering

Following guarantees are provided for the relative ordering of primitives
produced by a mesh shader, as they pertain to <<drawing-primitive-order,
primitive order>>.

  * When a task shader is used, mesh workgroups spawned from lower tasks
    will be ordered prior those workgroups from subsequent tasks.
  * All output primitives generated from a given mesh workgroup are passed
    to subsequent pipeline stages before any output primitives generated
    from subsequent input workgroups.
  * All output primitives within a mesh workgroup, will be generated in the
    ordering provided by the builtin primitive indexbuffer (from low address
    to high address).
