A pipeline cache is a pool that stores baked pipelines. It enables an application to reduce the pipeline creation overhead between pipeline runs and also between the subsequent application run. The following is the difference between the two:
vkCreateGraphicsPipelines
). By doing so, the underlying mechanism ensures that it reuses the pipeline if a similar one exists. This is widely useful in the creation of drawing objects that are redundant in nature, for example, paint brush strokes, sprites, mesh geometries, and so on.For more information on the specification and implementation of a pipeline cache object, refer to the following subsections.
A PCO can be used to create either a graphics (vkCreateGraphicsPipelines
) or compute pipeline (vkCreateComputePipelines
). Creating these pipelines with a PCO ensures the reusability of the pipeline objects. If the PCO does not contain a similar pipeline, then it creates a new one and adds it to its pool.
A PCO can be created using the vkCreatePipelineCache()
API. Upon its successful creation, it returns a VkPipelineCache
object. This API accepts four parameters, as described here:
VkResult vkCreatePipelineCache( VkDevice device, const VkPipelineCacheCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkPipelineCache* pPipelineCache);
The following are the various parameters accepted by the vkCreatePipelineCache()
API:
Parameters |
Description |
|
This is an object of the logical device (of the type |
|
This is the |
|
This controls host memory allocation. For more information, refer to the Host memory section in Chapter 5, Command Buffer and Memory Management in Vulkan. |
|
This returns the created |
The second parameter of the vkCreatePipelineCache()
API is of the type VkPipelineCacheCreateInfo
; this control structure contains the state/metadata information necessary to create and initialize the pipeline cache object. The following is the syntax of this structure:
typedef struct VkPipelineCacheCreateInfo { VkStructureType sType; const void* pNext; VkPipelineCacheCreateFlags flags; size_t initialDataSize; const void* pInitialData; } VkPipelineCacheCreateInfo;
Let's look at this structure's various fields:
Parameters |
Description |
|
This is the type information of the control structure. It must be specified as |
|
This could be a valid pointer to an extension-specific structure or |
|
This field is reserved for future use. |
|
This is the length of the data (in bytes) indicated by |
|
This field indicates the retrieved
datafrom some previously created pipeline cache. This will be used for initializing the contents of the newly created pipeline cache object. The initialization contents of the created pipeline cache object may remain empty if the data of
|
Two pipeline caches can be merged together into one using the vkMergePipelineCaches()
API. This API merges a destination pipeline cache into the source pipeline cache. It intakes four parameters. The first parameter device
is the logical device for which the merging will be carried out. The number of source pipeline caches is specified by pSrcCaches
with a count equal to srcCacheCount
. The final merging cache is stored in the destination pipeline cache called dstCache
.
The following is the syntax of this API:
VkResult vkMergePipelineCaches( VkDevice device, VkPipelineCache dstCache, uint32_t srcCacheCount, const VkPipelineCache* pSrcCaches);
A pipeline cache object can save its information in the form of streams of bytes. This stored information can be reused in future, when an application reruns or is executed again. The pipeline cache data can be retrieved using the vkGetPipelineCacheData()
API:
VkResult vkGetPipelineCacheData( VkDevice device, VkPipelineCache pipelineCache, size_t* dataSize, void* data);
The following table describes each parameter of this API:
Parameters |
Description |
|
This refers to the logical device that is used to create the pipeline cache object. |
|
This is the pipeline cache object from which the data is to be retrieved. |
|
When data is |
|
When |
The stored PCO information can be reused to preinitialize and populate the pipeline cache objects when the application starts. The compilation results may depend on the vendor and other device details. In order to ensure the application is compatible with the pipeline cache data, the header information can be used.
The retrieved data contains a header and a payload. The header provides the necessary information about the written data to ensure there is compatibility when an application runs the next time. The following diagram shows the format of the stored pipeline cache object:
The header consists of five fields, which may change in line with the specification. The header size is not fixed as per the specification but is read as the first four bytes from the data. This byte information encodes the length of the entire pipeline cache object's retrieved data header (in bytes), including each and every field in the header.
The following table specifies these fields' specification along with their size in bytes:
Offset |
Size |
Meaning |
0 |
4 |
This specifies the pipeline cache header's length in bytes. This 4-byte array of information is written with the least significant byte placed first in the sequence. |
4 |
4 |
This represents the header version ( |
8 |
4 |
This specifies the vendor ID, which is the same as |
12 |
4 |
This specifies the device ID, which is the same as |
16 |
4 |
This specifies a unique identifier that represents the pipeline cache object. The ID is equal to |
The PCO is implemented in VulkanPipeline.cpp
in the createPipelinceCache()
function. VkPipelineCacheCreateInfo
is initialized and passed to the vkCreatePipelineCache()
API. The initialDataSize
is 0 and pInitialData
is NULL
, as there is no old, retrievable PCO data to be used in the initialization of the created PCO:
void VulkanPipeline::createPipelineCache()
{
VkResult result;
VkPipelineCacheCreateInfo pipelineCacheInfo;
pipelineCacheInfo.sType = VK_STRUCTURE_TYPE_PIPELINE
_CACHE_CREATE_INFO;
pipelineCacheInfo.pNext = NULL;
pipelineCacheInfo.initialDataSize = 0;
pipelineCacheInfo.pInitialData = NULL;
pipelineCacheInfo.flags = 0;
// Create the pipeline cache using VkPipelineCacheCreateInfo
result = vkCreatePipelineCache(deviceObj->device,
&pipelineCacheInfo, NULL, &pipelineCache);
assert(result == VK_SUCCESS);
}
3.145.109.234