Skip to content

[PipelineStateCache] Several impl gaps prevented reliable persistent native PSO cache reuse in PipelineStateCacheD3D12 #811

Closed

Description

@hzqst

Summary

The D3D12 backend already supported in-process graphics/compute pipeline-library load/store and serialization, but several implementation gaps prevented reliable persistent native PSO cache reuse, especially when combined with IRenderStateCache archives and mesh pipelines.

Implementation gaps and impact

  1. Serialized native cache input was ignored.
    PipelineStateCacheD3D12Impl.cpp always called CreatePipelineLibrary(nullptr, 0, ...), regardless of PipelineStateCacheCreateInfo::pCacheData/CacheDataSize. Consequently, saving IPipelineStateCache::GetData() and supplying those bytes to a new cache did not restore the library: each new cache started empty.

  2. Archive hits dropped the caller's native cache.
    RenderStateCacheImpl.cpp did not populate PipelineStateUnpackInfo::pCache from PSOCreateInfo.pPSOCache. An archive hit therefore still created the underlying native PSO without caller's native cache. A serialized archive and a native driver pipeline library are distinct cache layers; hitting the former does not establish a hit in the latter. This forwarding gap is in shared GraphicsTools code, although it was encountered while enabling D3D12 persistence.

  3. Mesh PSOs bypassed the native pipeline library.
    PipelineStateD3D12Impl.cpp used ID3D12Device2::CreatePipelineState directly for mesh pipelines, with no pipeline-library load/store path.

  4. Display names were used as library keys.
    Graphics/compute cache lookup and storage used PSODesc.Name, and unnamed pipelines skipped caching. Different shader/state variants sharing a display name competed for the same library entry. A descriptor mismatch can cause a load miss and subsequent duplicate-name store failure, preventing both variants from remaining reusable. This is a cache-reuse problem; it does not by itself establish that D3D12 returns an incorrect PSO.

Expected behavior / reproduction outline

On a device supporting D3D12 pipeline libraries:

  1. Create an empty IPipelineStateCache.
  2. Create graphics/compute PSOs with pPSOCache set, serialize with GetData(), and retain the bytes.
  3. Recreate the device/cache and pass those bytes through pCacheData/CacheDataSize.
  4. Create the same pipelines, including through a restored IRenderStateCache archive.

Expected: the restored native library can satisfy compatible PSO requests.
Before the fix: the input bytes were ignored, and the archive-hit path also failed to forward the cache.

Additional cases: repeat with mesh pipelines, and with two different shader variants sharing the same display name. Both should be eligible for native caching and subsequent reuse.

Proposal fix

  • Restore and own initial library data. Copy supplied bytes into an owned IDataBlob and pass them to CreatePipelineLibrary. Retain the blob with the library through deferred release. If the data is rejected as invalid/incompatible, retry with an empty library. If pipeline libraries are unavailable, allow PSO creation to continue without native caching.
  • Forward the cache during archive unpacking. Set UnpackInfo.pCache = PSOCreateInfo.pPSOCache.
  • Add mesh library support. Query ID3D12PipelineLibrary1, try LoadPipeline for mesh PSO streams, and store newly created mesh PSOs. Populate an explicit primitive-topology subobject so creation and lookup use consistent descriptions.
  • Use deterministic content-based names. Generate PSO_2_<hash> from the root-signature hash, graphics pipeline description when applicable, shader stages, and effective shader bytecode after binding remapping. Hash strings by content rather than pointer address. This removes dependence on display names and supports same-name variants and unnamed pipelines.
  • Serialize library operations. Protect load/store/serialization with one mutex, including parallel PSO creation and cache snapshots.
  • Improve diagnostics. Verbose logging distinguishes cache hits/misses; expected misses and duplicate-store outcomes are informational rather than rendering errors.

@TheMostDiligent Would you accept a PR to fix the gaps?

Activity

  1. changed the title [-][PipelineStateCache] some impl gaps in PipelineStateCacheD3D12[/-] [+][PipelineStateCache] Several impl gaps prevented reliable persistent native PSO cache reuse in PipelineStateCacheD3D12[/+] on Oct 22, 2026
  2. TheMostDiligent commented on Oct 27, 2026

    @TheMostDiligent
    Contributor

    Fixed in #812

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions