xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/vulkan/doc/PipelineCreation.md (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1# Pipeline Compilation
2
3Vulkan pipelines depend on a number of state, most of which is known only at draw time.
4Unfortunately, creating pipelines is a heavy operation (in particular, converting SPIR-V to assembly
5and optimizing it), and doing so at draw time has multiple draw backs, including visible hitching.
6
7The first step taken towards alleviating this issue is to maximize ANGLE's use of available dynamic
8state.  This allows ANGLE to create fewer pipelines.  Simultaneously, ANGLE keeps the number of
9specialization constants to a minimum, to avoid recreating pipelines on state that might
10realistically change during the lifetime of the application.
11
12At link time, ANGLE warms up the pipeline cache by creating a few placeholder pipelines, in the hope
13that at draw time the pipeline cache is hit.  Without `VK_EXT_graphics_pipeline_library`, this is
14hit-or-miss.  With that extension though, ANGLE is able to create pipelines with less visible
15overhead.  This document focuses on ANGLE's use of `VK_EXT_graphics_pipeline_library`.
16
17Note that `VK_EXT_graphics_pipeline_library` divides the pipeline in four stages:
18
19- Vertex Input
20- Pre-Rasterization Shaders
21- Fragment Shader
22- Fragment Output
23
24In ANGLE, the two shaders subset are currently always created together.
25
26## At Link Time
27
28At link time, one pipeline library corresponding to the shader stages is pre-created.  Based on
29existing specialization constants and unavailability of some dynamic state, multiple variations of
30this pipeline library is created.  This helps warm the pipeline cache, but also allows ANGLE to pick
31these pipelines directly at draw time.  The pipelines are hashed and cached in the program
32executable.
33
34## At Draw Time
35
36At draw time, the vertex input and fragment output pipeline libraries are created similarly to how
37full pipelines are created, complete with hashing and caching them.  The cache for these pipelines
38is independent of the program executable.
39
40Then, the shaders pipeline is retrieved from the program executable's cache, and linked with the
41vertex input and fragment output pipelines to quickly create a complete pipeline for rendering.
42Note that creating vertex input and fragment output pipelines is relatively cheap, and as they are
43shared between programs, there are also few of them.
44
45Unfortunately, linked pipelines may not be as efficient as complete pipelines.  This largely depends
46on the hardware and driver; for example, some drivers optimize the vertex shader based on the vertex
47input, or implement the fragment output stage as part of the fragment shader.  To gain back the
48efficiency of the pipeline, ANGLE uses background threads to compile monolithic pipelines with all
49the necessary state.  Once the monolithic pipeline is ready, it's handle is swapped with the linked
50pipeline.
51
52The thread monolithic pipeline creation is orchestrated by the share group.  Currently, only one
53pipeline creation job is allowed at a time.  Additionally, posting these jobs is rate limited.  This
54is primarily because the app is functional with reasonable efficiency with linked pipelines, so
55ANGLE avoids racing to provide monolithic pipelines as fast as possible.  Instead, it ensures
56monolithic pipeline creation is inconspicuous and that it interferes as little as possible with the
57other threads the application may be running on other cores.
58
59To achieve this, each `PipelineHelper` whose handle refers to a linked pipeline holds a monolithic
60pipeline creation task to be scheduled.  Every time the pipeline handle is needed (i.e. at draw
61time, after a state change), `PipelineHelper::getPreferredPipeline` attempts to schedule this task
62through the share group.  The share group applies the aforementioned limits and may or may not post
63the task.  Eventually, future calls to `PipelineHelper::getPreferredPipeline` would end up
64scheduling the task and observing its termination.  At that point, the previous handle (from linked
65pipelines) is replaced by the handle created by the thread (a monolithic pipeline).
66