Repository navigation
[PipelineStateCache] Several impl gaps prevented reliable persistent native PSO cache reuse in PipelineStateCacheD3D12 #811
Description
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
-
Serialized native cache input was ignored.
PipelineStateCacheD3D12Impl.cppalways calledCreatePipelineLibrary(nullptr, 0, ...), regardless ofPipelineStateCacheCreateInfo::pCacheData/CacheDataSize. Consequently, savingIPipelineStateCache::GetData()and supplying those bytes to a new cache did not restore the library: each new cache started empty. -
Archive hits dropped the caller's native cache.
RenderStateCacheImpl.cppdid not populatePipelineStateUnpackInfo::pCachefromPSOCreateInfo.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. -
Mesh PSOs bypassed the native pipeline library.
PipelineStateD3D12Impl.cppusedID3D12Device2::CreatePipelineStatedirectly for mesh pipelines, with no pipeline-library load/store path. -
Display names were used as library keys.
Graphics/compute cache lookup and storage usedPSODesc.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:
- Create an empty
IPipelineStateCache. - Create graphics/compute PSOs with
pPSOCacheset, serialize withGetData(), and retain the bytes. - Recreate the device/cache and pass those bytes through
pCacheData/CacheDataSize. - Create the same pipelines, including through a restored
IRenderStateCachearchive.
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
IDataBloband pass them toCreatePipelineLibrary. 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, tryLoadPipelinefor 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
[-][PipelineStateCache] some impl gaps in PipelineStateCacheD3D12[/-][+][PipelineStateCache] Several impl gaps prevented reliable persistent native PSO cache reuse in PipelineStateCacheD3D12[/+]TheMostDiligent commentedon Oct 27, 2026
Fixed in #812