Caching pipeline objects with a PCO

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:

  • Between pipelines: The pipeline construction can be reused when new pipelines are created. The pipeline cache object is passed as a parameter to the pipeline creator API (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.
  • Between applications: While creating a pipeline, you deal with a lot of pipeline state objects, which is an expensive path. Reusability across running applications is a wise design and is efficient in terms of execution time and memory space. A pipeline cache inside a Vulkan application can be effectively reused by serializing the pipeline cache objects. The application retrieves the stored pipeline object from the serialized pipeline cache and preinitializes it. In subsequent runs, the same serialized PCOs can be reused across multiple application runs.

For more information on the specification and implementation of a pipeline cache object, refer to the following subsections.

Creating a pipeline cache object

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

device

This is an object of the logical device (of the type VkDevice) that is used to create the pipeline cache object (VkPipelineCache).

pCreateInfo

This is the VkPipelineCacheCreateInfo control structure that contains the metadata or state information that will be used to create the PCO object.

pAllocator

This controls host memory allocation. For more information, refer to the Host memory section in Chapter 5, Command Buffer and Memory Management in Vulkan.

pPipelineCache

This returns the created VkPipelineCache object pointer.

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

sType

This is the type information of the control structure. It must be specified as VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO.

pNext

This could be a valid pointer to an extension-specific structure or NULL.

flags

This field is reserved for future use.

initialDataSize

This is the length of the data (in bytes) indicated by initialData. If this field value is 0, then it signifies that the pipeline cache will be initially empty. Then pInitialData is ignored.

pInitialData

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 pInitialData is incompatible with the device.

Merging pipeline caches

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); 

Retrieving data from pipeline caches

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

device

This refers to the logical device that is used to create the pipeline cache object.

pipelineCache

This is the pipeline cache object from which the data is to be retrieved.

dataSize

When data is NULL, this field is used to query the size of the pipeline cache data in bytes from the pipelineCache object.

data

When dataSize is non-zero, this API reads the dataSize bytes from the pipelineCache object and retrieves the data.

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:

Retrieving data from pipeline caches

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 (VkPipelineCacheHeaderVersion) of the pipeline cache. This is an array of bytes with the least significant byte placed first.

8

4

This specifies the vendor ID, which is the same as VkPhysicalDeviceProperties::vendorID. This is a 4-byte array with the least significant byte placed first.

12

4

This specifies the device ID, which is the same as VkPhysicalDeviceProperties::deviceID. This is also a 4-byte array with the least significant byte placed first.

16

4

This specifies a unique identifier that represents the pipeline cache object. The ID is equal to VkPhysicalDeviceProperties::pipelineCacheUUID.

Implementing the PCO

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); 
} 
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.109.234