Skip to content

vulkan persistent pipeline cache and shader spirv code cache implementation #6248

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 19 commits into
base: master
Choose a base branch
from

Conversation

CLV-Iclucia
Copy link

Add Persistent Vulkan Pipeline Cache and Persistent Shader SPIR-V Cache

Changes

  • Implemented persistent save/load APIs for PipelineCache, enabling serialization of VkPipelineCache data to disk and reuse across application runs.
  • Introduced strict validation for cache consistency, including:
    • data hash verification
    • GPU info
    • ABI (32 bit or 64 bit)
  • Developed a separate on-disk cache mechanism for compiled shader SPIR-V binaries to avoid redundant shader compilation and improve pipeline build efficiency across runs.

Design Considerations

  • Save VkPipeline cache to the disk to accelerate pipeline creation.
  • Most of the time, compiling source code to spirv code is the bottleneck so I also designed a persistent spirv code cache to accelerate compiling across runs.

Testing

  • Verified robustness for pipeline cache in various situations like file corruption and multi-threading.
  • Passed all the current tests on Windows.

Performance

In a single pipeline creation test, the time taken for creating a pipeline is reduced from 90ms to 0.4ms using the two caches across runs (mocked by creating and destroying GPU repeatedly) on my PC and this is mainly contributed by spirv code cache.

The CPU is AMD Ryzen 7 5800H and the GPU is Nvidia RTX 3060.

pipeline cache test creation time (without cache): 90.87 ms
pipeline cache test creation time (with cache): 0.37 ms

Impact

  • Now ncnn users might need to manually load/save the pipeline cache, or customize spirv code cache saving directories.
  • Updating ncnn might need to change the ncnn_version in spirv cache header.

Questions for Review

1. Cross-platform file operations

The project currently lacks a unified cross-platform file API due to using C++11 (like renaming file). I implemented platform-specific file handling within the relevant pipelinecache.cpp files.
Would it be better to extract these into a cross-platform file module? Any recommendations or existing patterns in the project?

2. SPIR-V cache invalidation strategy

Multiple factors affect the generated SPIR-V, such as shader source, glslang version, and how ncnn handles device extensions and options.
I combined these into a single ncnn_version field in the spirv code cache header to invalidate caches on changes.
Is this approach sufficient? Are there better versioning or change-tracking strategies you recommend?

3. Testing and API exposure for SPIR-V cache

Exposing many interfaces to manipulate the SPIR-V cache risks complexity, yet hiding them makes thorough testing difficult.
What is the best practice here? Controlled internal APIs for testing, or relying on integration tests?

4. Security of SPIR-V cache files

If a cached SPIR-V file is maliciously altered (content and hash), there's a risk of running compromised shaders when loading the cache.
Do you have suggestions on mitigating this risk?

@tencent-adm
Copy link
Member

tencent-adm commented Aug 11, 2025

CLA assistant check
All committers have signed the CLA.

Copy link

The binary size change of libncnn.so (bytes)

architecture base size pr size difference
x86_64 15648008 15671312 +23304 ⚠️
armhf 6649020 6667484 +18464 ⚠️
aarch64 9987736 9990752 +3016 ⚠️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants