Proper way to do PSO Precaching for Niagara systems

Hello, we’re trying to use preloading to cover 100% of assets used in the game, but we’re running into issues specifically with runtime spawned VFX.

Most VFX attached to characters (imagine an attack ability) seems to be working fine, but we’re running into issues when we read from other data to decide which ones to spawn at runtime(imagine on-hit effects). We tried using two manual load strategy where we gather all the VFX that can be used as soft references, and either

Strategy 1: call async load

UAssetManager::GetStreamableManager().RequestAsyncLoad(
    NewPath,
    FStreamableDelegate::CreateUObject(this, &UFLXNiagaraHolderSubsystem::HandlePreloadComplete));

Strategy 2: Loading + Force postload

UNiagaraSystem* System = Cast<UNiagaraSystem>(SystemPath.TryLoad())
...
System->SetFlags(RF_NeedPostLoad);
System->SetFlags(RF_ForcePostLoad);
System->ConditionalPostLoad();

Since the preloading logic is in postload, I would expect them to be triggered. But neither has worked so far.

I’ve provided a demo of our set up in the attached files, this is more so to illustrate how we’re loading. The project is in 5.6, but I was seeing similar behavior in 5.8. r.PSOPrecache.Validation should be set to 2, but I think the PSO is just making it in time so it’s not reporting a miss.

My question is:

  1. What is the preferred strategy to preload runtime Niagara effects? Via data assets?
  2. Why is there misses being triggered when things are being precached?
  3. Is there significant difference between 5.6 and 5.8 with niagara precaching?
    [Attachment Removed]

Steps to Reproduce

  1. Delete local DXCache (C:\Users\USERNAME\AppData\Local\NVIDIA\DXCache) (or run with -clearPSODriverCache)
  2. open the project, press L to trigger the VFX(NS_TestVFX)
  3. open logs, observe that there technically is a miss on M_JOYCE_MAT_1, but it made it in time because this is a light level. This won’t be the case in a more graphically intense level.
    [Attachment Removed]

Hi, thanks for reaching out about this, and for sending along the additional files with your repro steps.

A data asset can be used, but it shouldn’t make or break this sort of issue.

Between 5.6 and 5.8, we added a readiness setting (which delays showing a system to avoid hitching), and some improvements / fixes to the precaching pipeline.

For clarity’s sake, are you using Substrate in 5.6, or was the example material a Substrate type just due to that being the default in 5.8?

In the meantime, I’ll look into this further.

[Attachment Removed]

Hello, Camille, thanks for the response!

We’re not using substrate in 5.6, the material was defaulted to that for 5.8, sorry!

I think for us in 5.6, I’m seeing is that materials are going through precaching pipeline and have generated caches. However when queried some materials always have a mismatch. I’ve done some other debugging and it seems like it has to do with the asset itself, in short:

  • always happens on Niagara VFXs
  • it’s conditionally triggered (if event A doesn’t happen, Niagara system may never be used)
  • independent of loading method, emitter type, etc.

I’m still investigating what’s the difference when a request hits/misses. But please let me know if there’s extra information I can provide to help with this.

[Attachment Removed]

Hi, no worries, that removes the non-production version of Substrate from the equation. A few other questions:

Are you using PSO Bundles and PSO Precaches, or Precaches only? Using both is a less-tested combination for us internally (though they have been used by other developers).

Have you already tried gathering PSOs via the playthrough method rather than the directly-managed method? Did that yield the same kind of misses as your current setup?

Does your project have a custom mesh pass or dynamic Render State changes that those materials use?

[Attachment Removed]

I posted an update, but I wanted to provide this also as supplementary information. Here’s an example from the actual project, you can try to trace through M_Matrix_Base_Blink_Smoke. It’s reporting for a EPSOPrecacheMissType::ShadersOnly type miss, however if you trace through the previous logs we are definitely caching the materials. I think that’s the biggest point of disconnect, where precaching is happening but it’s not being read on request?

[Attachment Removed]