Pipelines¶
A pipeline is a baked version of a program that runs on the GPU. Draw and dispatch commands run on these pipelines. Blender makes use of two type of pipelines Graphics pipelines and Compute pipelines.
Source references
- gpu/vulkan/vk_pipeline_pool.hh
- gpu/vulkan/vk_pipeline_pool.cc
API¶
classDiagram
class VKPipelinePool{
get_or_create_graphics_pipeline(VKGraphicsInfo, ...)
get_or_create_compute_pipeline(VKComputeInfo, ...)
read_from_disk()
write_to_disk()
}
get_or_create_*_pipeline
methods are used to retrieve an already build pipeline or create a new one when
the pipeline hasn't been used yet. Both use a info class that contains all the variables to identify
pipelines and to construct a new one. It is a subset when Vulkan uses in the vkCreateGraphicsPipeline
and
vkCreateComputePipeline
functions as we want to keep these structs small so lookup can be fast.
Graphic pipeline¶
A graphics pipeline is used by draw commands. The pipeline has multiple stages including the geometry assembly, vertex stage, fragment stage, depth testing and storing the result in the frame buffer.
If these stages change a new pipeline will be created to support the change. Blender caches pipelines so when an identical pipeline is requested as a previous one it doesn't need to be baked again. Making sure that pipeline handles are 1:1 allows us to also do better scheduling as we can ground similar calls together.
classDiagram
class VKGraphicsInfo {
state: GPUState
mutable_state: GPUMutableState
vk_pipeline_layout: VkPipelineLayout
specialization_constants: [SpecializationConstant::Value]
}
class VertexIn["VKGraphicsInfo::VertexIn"] {
vk_topology: VkPrimitiveTopology
attributes: [VkVertexInputAttributeDescription]
bindings: [VkVertexInputBindingDescription]
}
class PreRasterization["VKGraphicsInfo::Prerasterization"]{
vk_vertex_module: VkShaderModule
vk_geometry_module: VkShaderModule
}
class FragmentShader["VKGraphicsInfo::FragmentShader"] {
vk_shader_module: VkShaderModule
viewports: [VkViewport]
scissors: [VkRect2D]
}
class FragmentOut["VKGraphicsInfo::FragmentOut"] {
depth_attachment_format: VkFormat
stencil_attachment_format: VkFormat
color_attachment_formats: [VkFormat]
}
VKGraphicsInfo *--> VertexIn
VKGraphicsInfo *--> PreRasterization
VKGraphicsInfo *--> FragmentShader
VKGraphicsInfo *--> FragmentOut
Activating a different pipeline can stall the work that the GPU is currently doing.
Compute pipeline¶
Compute pipelines are simple as it only has a single stage. Compute pipelines only change when shader specialization is needed (Specialization constants).
classDiagram
class VKComputeInfo {
vk_shader_module: VkShaderModule
vk_pipeline_layout: VkPipelineLayout
specialization_constants: [SpecializationConstantValue]
}
Disk cache¶
Blender stores a pipeline cache for the "static shaders". The file is stored in the user cache folder
vk-pipeline-cache/static.bin
. Pipeline caches are driver specific caches. What is included in this
cache isn't standardized. It is seen as data that a driver could be stored to be reusable for the next
time the same application is run.
Performance wise pipeline caches can reduce stuttering and typically don't have a large performance penalty when they need to be re-initialized (<1s during a whole Blender session).
The driver specific data is prefixed by data to identify if the cache can be used by the current driver /device combination and blender session.
packet-beta
title Blender pipeline cache file.
0-4: "#BC00"
5-8: "BLENDER_VERSION"
9-12: "BL_VERSION_PATCH"
13-21: "COMMIT HASH"
22-26: "data size"
27-31: "GPU vendor id"
32-36: "GPU device id"
37-40: "driver_version"
41-58: "pipeline cache UUID"
59-95: "Driver specific data"
BLENDER_VERSION
,BLENDER_VERSION_PATCH
andCOMMIT_HASH
is used to identify if Blender has changed.data size
contains the total number of bytes of the "Driver specific data field": To identify if driver specific data was stored completely.GPU vendor id
keeps track if a GPU of a different vendor is used.GPU device id
keeps track if a different GPU of a vendor is used.
Future¶
VK_KHR_shader_module_identifier
: Blender can query the pipeline cache to check if compilation step can be skipped as the shader is part of the pipeline cache already. This could also include skipping GLSL assembly as well.VK_EXT_graphics_pipeline_library
: Parts of a pipeline can be shared for example the geometry assembly could be identical between other pipelines and processing done in a totally different pipeline could reduce the bake time of the pipeline.