Best practice for rebuilding shaders at runtime.

Hi,

Is there a good example of building / re-building shaders on first boot and when the video drivers are updated?

Is there also functionality on how to get the percentage of the process while its happening so we can display a counter / spinner etc.?

Thanks,

Simon

Hi, are you merely interested in recompiling shaders or Pipeline State Objects (PSOs)? If you are interested in the latter, we have a guide on querying the number of PSOs that are actively compiled and how to display a loading screen based on that information. You can find it here: https://dev.epicgames.com/documentation/en\-us/unreal\-engine/pso\-precaching\-for\-unreal\-engine\#loading\-screen. I hope this helps, but let me know if anything is unclear.

Hi,

is this in packaged game or editor/development? Because we don’t compile shaders in a packaged game but only PSOs. These are compiled via PSO precaching by default using background threads. The number of pending compilations can be retrieved via the link shared above. You can call FShaderPipelineCache::NumPrecompilesRemaining() or use a blueprint function to retrieve that value.

Hope that helps,

Kenzo

Hi,

Let me provide you with more information to address your questions. I will assume you are referring to the PSO precaching system, not the Bundled PSO cache, which is another feature of the engine.

Saving out the GPU card / Driver Version to user game settings --- What functions should we use?

Please note that you do not need to save the GPU information and/or driver version for PSO precaching. PSO precaching can retrieve the relevant information through the RHI, which interacts with the specified platform. If you have a packaged game, PSO precaching will be able to fetch the compiled shader and other relevant pipeline state information on the fly and send off PSO compilation requests to the driver all on its own. The compiled PSO is then stored in a local cache, which the GPU vendor’s driver manages.

On boot check against what was saved out if changed cache the PSO’s --- How do I create a clean cache of the PSO’s?

You do not need to perform any checks against the PSO cache at start-up. The checks are handled by the precaching system, which fetches the compiled PSOs from the driver cache. You can clear the platform’s driver cache by using the -clearPSODriverCache command-line argument to test and validate whether the PSO precaching system is picking up.

With that being said, I would strongly suggest reading the PSO precaching guide to further familiarize yourself with the various configuration settings you can toggle: https://dev.epicgames.com/documentation/en\-us/unreal\-engine/pso\-precaching\-for\-unreal\-engine

Hi Simon,

Unfortunately, I am unable to tell you why the stat view is empty. Have you verified you have PSO validation running via r.PSOPrecache.Validation?

“One idea: They are checking for FShaderPipelineCache::NumPrecompilesRemaining() to not be ‘0’, if not zero then display a screen showing the progress bar. Depending on title depends on time to do all the work.”

I cannot speak to how other UE titles implement this, but I can confirm that Fortnite uses this mechanism for its loading screen.

‘r.PSOPrecache.Resources’ defaults to ‘off’

The source code states: “Precache all possible used PSOs by resources during Postload (default 0 if PSOPrecaching is enabled)”, so I would recommend you do not turn that on when you want to use PSO precaching.

r.PSOPrecache.GlobalShaders defaults to ‘off’.

The wording for that particular cvar description is a bit off, and we will look to fix that up in a future update. For now, I would ignore the part about the IsDynamicShaderPreloadingEnabled variable needing to be enabled, as that got refactored out in a previous UE version.

Lastly, I recommend reading the guide I have posted above and the PSO Precaching source code to gain a good understanding of how to leverage precaching for your own title: https://dev.epicgames.com/documentation/en-us/unreal-engine/pso-precaching-for-unreal-engine

Hi TIm,

Thank you for the link.

Building shaders or PSO’s what is the best practice?

Do you have a code snippet for doing both? Having some code would help a lot.

Thanks,

Simon

Hi Kenzo,

This is just for packaged builds.

What I really need is the flow.

What I see needing to be done.

  1. Saving out the GPU card / Driver Version to user game settings --- What functions should we use?
  2. On boot check against what was saved out if changed cache the PSO’s --- How do I create a clean cache of the PSO’s?

What function do I call to kick it off?

These should all be set to ‘true’?

r.PSOPrecaching

r.PSOPrecache.Components

r.PSOPrecache.Resources

r.PSOPrecache.GlobalShaders ?

any others to be set?

Then just call ‘PrecachePSOs();’ ?

Then of course wait on FShaderPipelineCache::NumPrecompilesRemaining() to check for completion.

Yes precaching system.

Thank you for the info. But I want to run a scenario past you and understand what these titles are doing.

I will pick some latest titles like KEEPER, OUTER WORLDS 2 both built with UE5. Plus many more. I even believe FORTNITE does this too.

When the game boots they will give a message “Compiling Shaders” which I presume is compiling PSO’s really.

They will show a progress bar usually.

So how are they handling this under the hood.

One idea:

They are checking for FShaderPipelineCache::NumPrecompilesRemaining() to not be ‘0’, if not zero then display a screen showing the progress bar. Depending on title depends on time to do all the work.

Or is it like I said checking for driver updates themselves and kicking off a pre-compile or deleting the cache, … ???

To capture all PSO’s seems like these should be all set to ‘true’.

r.PSOPrecache.Components

r.PSOPrecache.Resources

r.PSOPrecache.GlobalShaders

Should these be ‘true’?

‘r.PSOPrecache.Resources’ defaults to ‘off’.

r.PSOPrecache.GlobalShaders defaults to ‘off’.

The verbage here doesn’t make full sense.

TEXT("r.PSOPrecache.GlobalShaders"),
0,
TEXT("Precache global shaders during startup (disable(0) - only compute shaders(1) - all global shaders(2).\n") 
TEXT("Note: r.PSOPrecache.GlobalShaders == 2 is only supported when IsDynamicShaderPreloadingEnabled is enabled."),

What is ‘IsDynamicShaderPreloadingEnabled’? Find no reference.

Want to get rid of the issues when levels load and items pop in.

Why would this all be empty?

[Image Removed]