Skip to content

Pipeline cache serialization/deserialization investigation #3716

@expenses

Description

@expenses

Goal

It would be neat and useful to have an implementation of get_pipeline_cache_data on all modern platforms (Vulkan, DX12, Metal). Along with the corresponding code in create_pipeline_cache, this would allow for being able to cache the pipelines to disk on all backends, giving a good performance boost when a lot of pipelines are used.

Status

Vulkan

The Vulkan API has this get_pipeline_cache_data function built in.

Metal

Edit: disregard this whole section, see #3716 (comment).

The Metal backend has a pipeline cache:

pub struct PipelineCache {
#[cfg(feature = "cross")] //TODO: Naga path
pub(crate) modules:
FastStorageMap<spirv_cross::msl::CompilerOptions, FastStorageMap<Vec<u32>, ModuleInfo>>,
}

However there is no way to serialize or deserialize it at present.

The key blocker for this is that the ModuleInfo struct stores a metal::Library:

#[derive(Clone, Debug)]
pub struct ModuleInfo {
pub library: metal::Library,
pub entry_point_map: EntryPointMap,
pub rasterization_enabled: bool,
}

While there is no way in the Metal API to serialize a MTLLibrary (the underlying type), there is a serialize function for MTLDynamicLibrary which I believe we could convert into. It serializes directly into a file though, which is pretty gross. Presumably we'd then have to read back from this file.

The other option would be to just store the metal source code for the shader that has been converted from spir-v. This would not give as big a performance improvement though.

MoltenVK

MoltenVK implements a pipeline cache with MVKPipelineCache. Similar to what we do with metal, this stores MVKShaderLibraryCaches which in turn store MVKShaderLibrarys. When implementing getPipelineCacheData, it writes the metal source code, similar to what I suggest as an option above.

As an example of this, here's some of the output of a pipeline cache I generated:

 &Y'v�˺GC�^\��@ mainzzzzzmain0>#include <metal_stdlib>
#include <simd/simd.h>

using namespace metal;

struct main0_out
{
    float4 uFragColor [[color(0)]];
};

struct main0_in
{
    float4 o_color [[user(locn0)]];
};

fragment main0_out main0(main0_in in [[stage_in]])
{
    main0_out out = {};
    out.uFragColor = in.o_color;
    return out;
}

TxC@�@mainzzzzzmain0�#include <metal_stdlib>
#include <simd/simd.h>
<...>

DX12

The DirectX 12 backend doesn't have a pipeline cache. However, there is an issue that lays out how one could be created: #2877, similar to what the Metal backend does.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions