Pipelines

The following figure shows a block diagram of the Vulkan pipelines. Some Vulkan commands specify geometric objects to be drawn or computational work to be performed, while others specify state controlling how objects are handled by the various pipeline stages, or control data transfer between memory organized as images and buffers. Commands are effectively sent through a processing pipeline, either a graphics pipeline, a ray tracing pipeline, or a compute pipeline.

The graphics pipeline can be operated in two modes, as either primitive shading or mesh shading pipeline.

Primitive Shading

The first stage of the graphics pipeline (Input Assembler) assembles vertices to form geometric primitives such as points, lines, and triangles, based on a requested primitive topology. In the next stage (Vertex Shader) vertices can be transformed, computing positions and attributes for each vertex. If tessellation and/or geometry shaders are supported, they can then generate multiple primitives from a single input primitive, possibly changing the primitive topology or generating additional attribute data in the process.

Cluster Culling Shading

When using the Cluster Culling Shader, a compute-like shader will perform cluster-based culling, a set of new built-in output variables are used to express visible cluster, in addition, a new built-in function is used to emit these variables from the cluster culling shader to the Input Assembler(IA) stage, then IA can use these variables to fetches vertices of visible cluster and drive vertex shader to work.

Mesh Shading

When using the mesh shading pipeline input primitives are not assembled implicitly, but explicitly through the (Mesh Shader). The work on the mesh pipeline is initiated by the application drawing a set of mesh tasks.

If an optional (Task Shader) is active, each task triggers the execution of a task shader workgroup that will generate a new set of tasks upon completion. Each of these spawned tasks, or each of the original dispatched tasks if no task shader is present, triggers the execution of a mesh shader workgroup that produces an output mesh with a variable-sized number of primitives assembled from vertices stored in the output mesh.

Common

The final resulting primitives are clipped to a clip volume in preparation for the next stage, Rasterization. The rasterizer produces a series of fragments associated with a region of the framebuffer, from a two-dimensional description of a point, line segment, or triangle. These fragments are processed by fragment operations to determine whether generated values will be written to the framebuffer. Fragment shading determines the values to be written to the framebuffer attachments. Framebuffer operations then read and write the color and depth/stencil attachments of the framebuffer for a given subpass of a render pass instance. The attachments can be used as input attachments in the fragment shader in a later subpass of the same render pass.

The compute pipeline is a separate pipeline from the graphics pipeline, which operates on one-, two-, or three-dimensional workgroups which can read from and write to buffer and image memory.

This ordering is meant only as a tool for describing Vulkan, not as a strict rule of how Vulkan is implemented, and we present it only as a means to organize the various operations of the pipelines. Actual ordering guarantees between pipeline stages are explained in detail in the synchronization chapter.

Each pipeline is controlled by a monolithic object created from a description of all of the shader stages and any relevant fixed-function stages. Linking the whole pipeline together allows the optimization of shaders based on their input/outputs and eliminates expensive draw time state validation.

A pipeline object is bound to the current state using vkCmdBindPipeline. Any pipeline object state that is specified as dynamic is not applied to the current state when the pipeline object is bound, but is instead set by dynamic state setting commands.

No state, including dynamic state, is inherited from one command buffer to another.

VkPipelineOpaque handle to a pipeline object

Multiple Pipeline Creation

Multiple pipelines can be created in a single call by commands such as vkCreateExecutionGraphPipelinesAMDX, vkCreateRayTracingPipelinesKHR, vkCreateRayTracingPipelinesNV, vkCreateComputePipelines, and vkCreateGraphicsPipelines.

The creation commands are passed an array pCreateInfos of Vk*PipelineCreateInfo structures specifying parameters of each pipeline to be created, and return a corresponding array of handles in pPipelines. Each element index i of pPipelines is created based on the corresponding element i of pCreateInfos.

Applications can group together similar pipelines to be created in a single call, and implementations are encouraged to look for reuse opportunities when creating a group.

When attempting to create many pipelines in a single command, it is possible that creation may fail for a subset of them. In this case, the corresponding elements of pPipelines will be set to VK_NULL_HANDLE. If creation fails for a pipeline despite valid arguments (for example, due to out of memory errors), the VkResult code returned by the pipeline creation command will indicate why. The implementation will attempt to create all pipelines, and only return VK_NULL_HANDLE values for those that actually failed.

If creation fails for a pipeline that has the VK_PIPELINE_CREATE_EARLY_RETURN_ON_FAILURE_BIT set in its Vk*PipelineCreateInfo, pipelines at an index in the pPipelines array greater than or equal to that of the failing pipeline will be set to VK_NULL_HANDLE.

If creation fails for multiple pipelines, the returned VkResult must be the return value of any one of the pipelines which did not succeed. An application can reliably clean up from a failed call by iterating over the pPipelines array and destroying every element that is not VK_NULL_HANDLE.

If the entire command fails and no pipelines are created, all elements of pPipelines will be set to VK_NULL_HANDLE.

Compute Pipelines

Compute pipelines consist of a single static compute shader stage and the pipeline layout.

The compute pipeline represents a compute shader and is created by calling vkCreateComputePipelines with module and pName selecting an entry point from a shader module, where that entry point defines a valid compute shader, in the VkPipelineShaderStageCreateInfo structure contained within the VkComputePipelineCreateInfo structure.

vkCreateComputePipelinesCreates a new compute pipeline object
VkComputePipelineCreateInfoStructure specifying parameters of a newly created compute pipeline
VkPipelineShaderStageCreateInfoStructure specifying parameters of a newly created pipeline shader stage
VkPipelineShaderStageCreateFlagsBitmask of VkPipelineShaderStageCreateFlagBits
VkPipelineShaderStageCreateFlagBitsBitmask controlling how a pipeline shader stage is created
VkShaderStageFlagBitsBitmask specifying a pipeline stage
VkShaderStageFlagsBitmask of VkShaderStageFlagBits
VkPipelineShaderStageRequiredSubgroupSizeCreateInfoStructure specifying the required subgroup size of a newly created pipeline shader stage
VkSubpassShadingPipelineCreateInfoHUAWEIStructure specifying parameters of a newly created subpass shading pipeline
vkGetDeviceSubpassShadingMaxWorkgroupSizeHUAWEIQuery maximum supported subpass shading workgroup size for a give render pass
VkPipelineRobustnessCreateInfoEXTStructure controlling the robustness of a newly created pipeline shader stage
VkPipelineRobustnessBufferBehaviorEXTEnum controlling the robustness of buffer accesses in a pipeline stage
VkPipelineRobustnessImageBehaviorEXTEnum controlling the robustness of image accesses in a pipeline stage
VkPipelineShaderStageModuleIdentifierCreateInfoEXTStructure specifying an identifier for a shader module

If a compute pipeline is going to be used in Device-Generated Commands by specifying its pipeline token with VkBindPipelineIndirectCommandNV, then that pipeline’s associated metadata must be saved at a specified buffer device address for later use in indirect command generation. The buffer device address must be specified at the time of compute pipeline creation with VkComputePipelineIndirectBufferInfoNV structure in the pNext chain of VkComputePipelineCreateInfo.

VkComputePipelineIndirectBufferInfoNVStructure describing the device address where pipeline’s metadata will be saved
vkCmdUpdatePipelineIndirectBufferNVUpdate the indirect compute pipeline’s metadata

Graphics Pipelines

Graphics pipelines consist of multiple shader stages, multiple fixed-function pipeline stages, and a pipeline layout.

vkCreateGraphicsPipelinesCreate graphics pipelines
VkGraphicsPipelineCreateInfoStructure specifying parameters of a newly created graphics pipeline
VkPipelineRenderingCreateInfoStructure specifying attachment formats
VkPipelineCreateFlags2CreateInfoKHRExtended pipeline create flags
VkPipelineCreateFlagBits2KHRBitmask controlling how a pipeline is created
VkPipelineCreateFlags2KHRBitmask of VkPipelineCreateFlagBits2KHR
VkPipelineCreateFlagBitsBitmask controlling how a pipeline is created
VkPipelineCreateFlagsBitmask of VkPipelineCreateFlagBits
VkGraphicsPipelineLibraryCreateInfoEXTStructure specifying the subsets of the graphics pipeline being compiled
VkGraphicsPipelineLibraryFlagsEXTBitmask of VkGraphicsPipelineLibraryFlagBitsEXT
VkGraphicsPipelineLibraryFlagBitsEXTBitmask specifying the subset of a graphics pipeline to compile
VkPipelineDynamicStateCreateInfoStructure specifying parameters of a newly created pipeline dynamic state
VkPipelineDynamicStateCreateFlagsReserved for future use
VkDynamicStateIndicate which dynamic state is taken from dynamic state commands

Valid Combinations of Stages for Graphics Pipelines

Primitive processing can be handled either on a per primitive basis by the vertex, tessellation, and geometry shader stages, or on a per mesh basis using task and mesh shader stages. If the pipeline includes a mesh shader stage, it uses the mesh pipeline, otherwise it uses the primitive pipeline.

If a task shader is omitted, the task shading stage is skipped.

If tessellation shader stages are omitted, the tessellation shading and fixed-function stages of the pipeline are skipped.

If a geometry shader is omitted, the geometry shading stage is skipped.

If a fragment shader is omitted, fragment color outputs have undefined: values, and the fragment depth value is determined by Fragment Operations state. This can be useful for depth-only rendering.

Presence of a shader stage in a pipeline is indicated by including a valid VkPipelineShaderStageCreateInfo with module and pName selecting an entry point from a shader module, where that entry point is valid for the stage specified by stage.

Presence of some of the fixed-function stages in the pipeline is implicitly derived from enabled shaders and provided state. For example, the fixed-function tessellator is always present when the pipeline has valid Tessellation Control and Tessellation Evaluation shaders.

Graphics Pipeline Shader Groups

Graphics pipelines can contain multiple shader groups that can be bound individually. Each shader group behaves as if it was a pipeline using the shader group’s state. When the pipeline is bound by regular means, it behaves as if the state of group 0 is active, use vkCmdBindPipelineShaderGroupNV to bind an individual shader group.

The primary purpose of shader groups is allowing the device to bind different pipeline state using Device-Generated Commands.

VkGraphicsPipelineShaderGroupsCreateInfoNVStructure specifying parameters of a newly created multi shader group pipeline
VkGraphicsShaderGroupCreateInfoNVStructure specifying override parameters for each shader group

Ray Tracing Pipelines

Ray tracing pipelines consist of multiple shader stages, fixed-function traversal stages, and a pipeline layout.

VK_SHADER_UNUSED_KHRSentinel for an unused shader index
vkCreateRayTracingPipelinesNVCreates a new ray tracing pipeline object
vkCreateRayTracingPipelinesKHRCreates a new ray tracing pipeline object
VkRayTracingPipelineCreateInfoNVStructure specifying parameters of a newly created ray tracing pipeline
VkRayTracingPipelineCreateInfoKHRStructure specifying parameters of a newly created ray tracing pipeline
VkRayTracingShaderGroupCreateInfoNVStructure specifying shaders in a shader group
VkRayTracingShaderGroupCreateInfoKHRStructure specifying shaders in a shader group
VkRayTracingShaderGroupTypeKHRShader group types
VkRayTracingPipelineInterfaceCreateInfoKHRStructure specifying additional interface information when using libraries
vkGetRayTracingShaderGroupHandlesKHRQuery ray tracing pipeline shader group handles
vkGetRayTracingCaptureReplayShaderGroupHandlesKHRQuery opaque capture replay data for pipeline shader group handles

Ray tracing pipelines can contain more shaders than a graphics or compute pipeline, so to allow parallel compilation of shaders within a pipeline, an application can choose to defer compilation until a later point in time.

vkCompileDeferredNVDeferred compilation of shaders
vkGetRayTracingShaderGroupStackSizeKHRQuery ray tracing pipeline shader group shader stack size
VkShaderGroupShaderKHRShader group shaders
vkCmdSetRayTracingPipelineStackSizeKHRSet the stack size dynamically for a ray tracing pipeline

Pipeline Destruction

vkDestroyPipelineDestroy a pipeline object

Pipeline Derivatives

A pipeline derivative is a child pipeline created from a parent pipeline, where the child and parent are expected to have much commonality.

The goal of derivative pipelines is that they be cheaper to create using the parent as a starting point, and that it be more efficient (on either host or device) to switch/bind between children of the same parent.

A derivative pipeline is created by setting the VK_PIPELINE_CREATE_DERIVATIVE_BIT flag in the Vk*PipelineCreateInfo structure. If this is set, then exactly one of basePipelineHandle or basePipelineIndex members of the structure must have a valid handle/index, and specifies the parent pipeline. If basePipelineHandle is used, the parent pipeline must have already been created. If basePipelineIndex is used, then the parent is being created in the same command. VK_NULL_HANDLE acts as the invalid handle for basePipelineHandle, and -1 is the invalid index for basePipelineIndex. If basePipelineIndex is used, the base pipeline must appear earlier in the array. The base pipeline must have been created with the VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT flag set.

Pipeline Cache

VkPipelineCacheOpaque handle to a pipeline cache object

Creating a Pipeline Cache

vkCreatePipelineCacheCreates a new pipeline cache
VkPipelineCacheCreateInfoStructure specifying parameters of a newly created pipeline cache
VkPipelineCacheCreateFlagsBitmask of VkPipelineCreateFlagBits
VkPipelineCacheCreateFlagBitsBitmask specifying the behavior of the pipeline cache

Merging Pipeline Caches

vkMergePipelineCachesCombine the data stores of pipeline caches

Retrieving Pipeline Cache Data

vkGetPipelineCacheDataGet the data store from a pipeline cache

Pipeline Cache Header

Applications can store the data retrieved from the pipeline cache, and use these data, possibly in a future run of the application, to populate new pipeline cache objects. The results of pipeline compiles, however, may depend on the vendor ID, device ID, driver version, and other details of the device. To enable applications to detect when previously retrieved data is incompatible with the device, the pipeline cache data must begin with a valid pipeline cache header.

Structures described in this section are not part of the Vulkan API and are only used to describe the representation of data elements in pipeline cache data. Accordingly, the valid usage clauses defined for structures defined in this section do not define valid usage conditions for APIs accepting pipeline cache data as input, as providing invalid pipeline cache data as input to any Vulkan API commands will result in the provided pipeline cache data being ignored.

VkPipelineCacheHeaderVersionOneStructure describing the layout of the pipeline cache header
VkPipelineCacheHeaderVersionEncode pipeline cache version

Destroying a Pipeline Cache

vkDestroyPipelineCacheDestroy a pipeline cache object

Specialization Constants

Specialization constants are a mechanism whereby constants in a SPIR-V module can have their constant value specified at the time the VkPipeline is created. This allows a SPIR-V module to have constants that can be modified while executing an application that uses the Vulkan API.

Specialization constants are useful to allow a compute shader to have its local workgroup size changed at runtime by the user, for example.

Each VkPipelineShaderStageCreateInfo structure contains a pSpecializationInfo member, which can be NULL to indicate no specialization constants, or point to a VkSpecializationInfo structure.

VkSpecializationInfoStructure specifying specialization information
VkSpecializationMapEntryStructure specifying a specialization map entry

In human readable SPIR-V:

From the above we have three specialization constants, one for each of the x, y & z elements of the WorkgroupSize vector.

Now to specialize the above via the specialization constants mechanism:

Then when calling vkCreateComputePipelines, and passing the VkSpecializationInfo we defined as the pSpecializationInfo parameter of VkPipelineShaderStageCreateInfo, we will create a compute pipeline with the runtime specified local workgroup size.

Another example would be that an application has a SPIR-V module that has some platform-dependent constants they wish to use.

In human readable SPIR-V:

From the above we have two specialization constants, one is a signed 32-bit integer and the second is a 32-bit floating-point value.

Now to specialize the above via the specialization constants mechanism:

It is legal for a SPIR-V module with specializations to be compiled into a pipeline where no specialization information was provided. SPIR-V specialization constants contain default values such that if a specialization is not provided, the default value will be used. In the examples above, it would be valid for an application to only specialize some of the specialization constants within the SPIR-V module, and let the other constants use their default values encoded within the OpSpecConstant declarations.

Pipeline Libraries

A pipeline library is a special pipeline that was created using the VK_PIPELINE_CREATE_LIBRARY_BIT_KHR and cannot be bound, instead it defines a set of pipeline state which can be linked into other pipelines. For ray tracing pipelines this includes shaders and shader groups. For graphics pipelines this includes distinct library types defined by VkGraphicsPipelineLibraryFlagBitsEXT. The application must maintain the lifetime of a pipeline library based on the pipelines that link with it.

This linkage is achieved by using the following structure within the appropriate creation mechanisms:

VkPipelineLibraryCreateInfoKHRStructure specifying pipeline libraries to use when creating a pipeline

Pipelines created with VK_PIPELINE_CREATE_LIBRARY_BIT_KHR libraries can depend on other pipeline libraries in VkPipelineLibraryCreateInfoKHR.

A pipeline library is considered in-use, as long as one of the linking pipelines is in-use. This applies recursively if a pipeline library includes other pipeline libraries.

Pipeline Binding

vkCmdBindPipelineBind a pipeline object to a command buffer
VkPipelineBindPointSpecify the bind point of a pipeline object to a command buffer
vkCmdBindPipelineShaderGroupNVBind a pipeline object

Interaction With Shader Objects

If the shaderObject feature is enabled, applications can use both pipelines and shader objects at the same time. The interaction between pipelines and shader objects is described in Interaction with Pipelines.

Dynamic State

When a pipeline object is bound, any pipeline object state that is not specified as dynamic is applied to the command buffer state. Pipeline object state that is specified as dynamic is not applied to the command buffer state at this time. Instead, dynamic state can be modified at any time and persists for the lifetime of the command buffer, or until modified by another dynamic state setting command, or made invalid by another pipeline bind with that state specified as static.

When a pipeline object is bound, the following applies to each state parameter:

  • If the state is not specified as dynamic in the new pipeline object, then that command buffer state is overwritten by the state in the new pipeline object. Before any draw or dispatch call with this pipeline there must not have been any calls to any of the corresponding dynamic state setting commands after this pipeline was bound.
  • If the state is specified as dynamic in the new pipeline object, then that command buffer state is not disturbed. Before any draw or dispatch call with this pipeline there must have been at least one call to each of the corresponding dynamic state setting commands. The state-setting commands must be recorded after command buffer recording was begun, or after the last command binding a pipeline object with that state specified as static, whichever was the latter.
  • If the state is not included (corresponding pointer in VkGraphicsPipelineCreateInfo was NULL or was ignored) in the new pipeline object, then that command buffer state is not disturbed. For example, mesh shading pipelines do not include vertex input state and therefore do not disturb any such command buffer state.

Dynamic state that does not affect the result of operations can be left undefined:.

For example, if blending is disabled by the pipeline object state then the dynamic color blend constants do not need to be specified in the command buffer, even if this state is specified as dynamic in the pipeline object.

Applications running on Vulkan implementations advertising an VkPhysicalDeviceDriverProperties::conformanceVersion less than 1.3.8.0 should be aware that rebinding the currently bound pipeline object may not reapply static state.

Pipeline Properties and Shader Information

vkGetPipelineExecutablePropertiesKHRGet the executables associated with a pipeline
VkPipelineExecutablePropertiesKHRStructure describing a pipeline executable
vkGetPipelinePropertiesEXTQuery pipeline properties
VkPipelinePropertiesIdentifierEXTStructure used to retrieve pipeline properties
VkPipelineInfoKHRStructure describing a pipeline
vkGetPipelineExecutableStatisticsKHRGet compile time statistics associated with a pipeline executable
VkPipelineExecutableInfoKHRStructure describing a pipeline executable to query for associated statistics or internal representations
VkPipelineExecutableStatisticKHRStructure describing a compile time pipeline executable statistic
VkPipelineExecutableStatisticFormatKHREnum describing a pipeline executable statistic
VkPipelineExecutableStatisticValueKHRA union describing a pipeline executable statistic
vkGetPipelineExecutableInternalRepresentationsKHRGet internal representations of the pipeline executable
VkPipelineExecutableInternalRepresentationKHRStructure describing the textual form of a pipeline executable internal representation
vkGetShaderInfoAMDGet information about a shader in a pipeline
VkShaderInfoTypeAMDEnum specifying which type of shader information to query
VkShaderStatisticsInfoAMDStatistical information about a particular shader within a pipeline
VkShaderResourceUsageAMDResource usage information about a particular shader within a pipeline

Pipeline Compiler Control

VkPipelineCompilerControlCreateInfoAMDStructure used to pass compilation control flags to a pipeline
VkPipelineCompilerControlFlagBitsAMDEnum specifying available compilation control flags
VkPipelineCompilerControlFlagsAMDBitmask of VkPipelineCompilerControlFlagBitsAMD

Pipeline Creation Feedback

VkPipelineCreationFeedbackCreateInfoRequest for feedback about the creation of a pipeline
VkPipelineCreationFeedbackFeedback about the creation of a pipeline or pipeline stage
VkPipelineCreationFeedbackFlagBitsBitmask specifying pipeline or pipeline stage creation feedback
VkPipelineCreationFeedbackFlagsBitmask of VkPipelineCreationFeedbackFlagBits