9.6. 管线缓存
管线缓存对象允许管线构造的结果可以在不同的管线之间,应用程序多次运行之间重用。 在不同管线之间重用是在创建多个关联管线时通过传递相同的管线缓存对象来实现的。 在应用程序多次运行之间重用是通过获取管线缓存内容、保存内容,在下一次运行时初始化管线之前使用它们。 管线缓存对象的内容是由Vulkan实现来管理的。 应用程序可以管理管线缓存对象消耗的主机端内存,控制从管线缓存对象中获取的数据的量的大小。
管线缓存对象通过VkPipelineCache
handles来表示:
VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkPipelineCache)
可调用如下命令来创建管线缓存对象:
VkResult vkCreatePipelineCache(
VkDevice device,
const VkPipelineCacheCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator,
VkPipelineCache* pPipelineCache);
-
device
是创建管线缓存的连接设备。 -
pCreateInfo
是一个指针,指向了一个aVkPipelineCacheCreateInfo
,包含着管线缓存的初始参数。 -
pAllocator
控制了CPU端内存分配,如 Memory Allocation 一章所描述。 -
pPipelineCache
是一个指针,指向了一个VkPipelineCache
handle,存放被返回的管线缓存对象。
注意
应用程序可以使用 |
一旦创建完成,一个管线缓存可以被传递到vkCreateGraphicsPipelines
和 vkCreateComputePipelines
命令。 如果传递到这些命令的一个管线缓存对象不是VK_NULL_HANDLE
,Vulkan实现将查询是否可重用它并更新。 在这些命令内使用管线缓存对象是内部同步的,同一个管线缓存对象可以在多线程中同时使用。
注意
Vulkan实现应该尽量限制critical sections 代码段对缓存的访问,亦即,最好比 |
VkPipelineCacheCreateInfo
数据结构定义如下:
typedef struct VkPipelineCacheCreateInfo {
VkStructureType sType;
const void* pNext;
VkPipelineCacheCreateFlags flags;
size_t initialDataSize;
const void* pInitialData;
} VkPipelineCacheCreateInfo;
-
sType
是数据结构的类型。 -
pNext
是NULL
或者一个指向拓展特定的数据结构的指针。 -
flags
被保留。 -
initialDataSize
是pInitialData
的字节大小。如果initialDataSize
为0,管线缓存将被初始为空。 -
pInitialData
是一个指针,指向了之前获取到的管线缓存数据。如果管线缓存数据和设备是不兼容的(如下有解释), 管线缓存将被初始化为空。如果initialDataSize
为0,pInitialData
将被忽略。
可以使用如下命令来合并管线缓存对象:
VkResult vkMergePipelineCaches(
VkDevice device,
VkPipelineCache dstCache,
uint32_t srcCacheCount,
const VkPipelineCache* pSrcCaches);
-
device
是拥有该管线缓存对象的逻辑设备。 -
dstCache
是存放合并产生的管线缓存的handle。 -
srcCacheCount
是 数组pSrcCaches
的大小。 -
pSrcCaches
是一个管线缓存handle的数组,将被合并到dstCache
。dstCache
之前的内容仍包含在合并之后的缓存中。
注意
The details of the merge operation are implementation dependent, but implementations should merge the contents of the specified pipelines and prune duplicate entries. |
可以使用如下命令从管线缓存对象中取出数据:
VkResult vkGetPipelineCacheData(
VkDevice device,
VkPipelineCache pipelineCache,
size_t* pDataSize,
void* pData);
-
device
是拥有该管线缓存对象的逻辑设备。 -
pipelineCache
是获取数据的目标管线缓存对象。 -
pDataSize
是一个指针,指向存放从管线缓存中获取的数据大小的变量,下面有描述。 -
pData
要么是NULL
,要么指向一个缓冲区。
若pData
是 NULL
,那么可以从管线缓存中取出的数据的最大大小通过 pDataSize
返回,以字节为单位。 否则,pDataSize
必须指向一个变量,由用户设置为 pData
所指向的buffer的大小(字节为单位), 函数返回时,变量将被覆盖为写入到pData
的数据量的大小。
若 pDataSize
比可以从管线缓存中取出的数据的最大大小要小,那么最多只有pDataSize
字节的数据将被写入pData
,vkGetPipelineCacheData
将返回VK_INCOMPLETE
。
写入pData
的任何数据都是有效的,可以用作VkPipelineCacheCreateInfo
数据结构的pInitialData
成员,从而传递给vkCreatePipelineCache
。
用相同的参数两次调用vkGetPipelineCacheData
必须要获取到完全相同的数据,除非在两次调用期间,其他的命令改变了缓存的内容。
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 initial bytes written to pData
must be a header consisting of the following members:
Offset | Size | Meaning |
---|---|---|
0 | 4 | length in bytes of the entire pipeline cache header written as a stream of bytes, with the least significant byte first |
4 | 4 | a |
8 | 4 | a vendor ID equal to |
12 | 4 | a device ID equal to |
16 | | a pipeline cache ID equal to |
The first four bytes encode the length of the entire pipeline header, in bytes. This value includes all fields in the header including the pipeline cache version field and the size of the length field.
The next four bytes encode the pipeline cache version. This field is interpreted as a VkPipelineCacheHeaderVersion
value, and must have one of the following values:
typedef enum VkPipelineCacheHeaderVersion {
VK_PIPELINE_CACHE_HEADER_VERSION_ONE = 1,
} VkPipelineCacheHeaderVersion;
A consumer of the pipeline cache should use the cache version to interpret the remainder of the cache header.
If pDataSize
is less than what is necessary to store this header, nothing will be written to pData
and zero will be written to pDataSize
.
可调用如下命令来销毁管线缓存:
void vkDestroyPipelineCache(
VkDevice device,
VkPipelineCache pipelineCache,
const VkAllocationCallbacks* pAllocator);
-
device
是销毁管线缓存的逻辑设备。 -
pipelineCache
是需要被销毁的管线缓存。 -
pAllocator
控制了主机端内存如何分配,如Memory Allocation一章所述。