PSO Precaching for Open Worlds

Since UE5.3 PSO Precaching is enabled by default. This should (in theory) precompile all needed PSOs, on level load.

In our project we are building a open world, similar to Project Titan.
As our content is streamed in on the fly, our initial loading screen does not catch all objects, the player might see in the world.

That is why, whenever a new tile is loaded, Unreal needs to gather all missing PSOs and compile them on the fly. This should (in theory) be async, while Unreal displays a default material.

Sadly it isn’t.

As you can see, unreal is creating Pipeline State objects, while the game Threat is waiting for them to finish. This causes huge spikes, which sometimes take over 1s. This mostly appears when a new chunk is loaded.
Our assumption is, that when Unreal loads in new content, it deems some shaders as critical and compiles them instantly, while blocking the game threat.

In their recent talk, they listed the pro’s and con’s of the new precaching system.
One con is “inconventient, when streaming tiles”.
That is the inconvenience we are facing right now. But what is the solution? Is there any?

Our last resort would be, to manually create the PSO Cache by playing the game. This is quite tedious though, as you need to play the whole content multiple times with different graphics settings.
So we would prefer any stutter-free solution over this. Be it delaying the object rendering, pre-compiling on game startup or drawing a default material.

reduce the number of shader combos you have. abuse the material instance system to it’s full potential. create “core” shaders. avoid dynamic shader switches. if you just switch out textures it will not create more shader combos / permutations.

on the loading end of things you can load and precache the whole game’s core shaders on the initial loading screen. or while you run the intro video. or just add a shader compile screen. just load and unload all types of objects that use all the different shader combos thruout the game. the compile time depends how well you implement the “core” and instanced it.

that’s how i would do it.

1 Like

So basically you would create a „demo level“ with all Static Meshes inside, and run this during game startup. Which will then precompile all shaders.
We are already using master materials and instancing.

That’s a good idea, we will try this out.

Is there a way to prevent hitches, in case we DO miss a PSO compile during load time?

i don’t think so. if it needs a shader combo you missed it’s gonna compile it on the fly.

Alright. We are currently working on a solution.

We were able to eliminate 90% of open world PSO stutter by copying our Post Processing and VFX/Lights into a demo scene and then importing every Static model/Niagara Effect/Skeletal Mesh using an editor script.

The player loads into that map, the PC compiles all shaders and then resumes to the game.

Our only headache right now are the landscape PSOs. We have ~20 Material Layers and unreal creates a PSO for every combination of layers. That makes around 1Million if I am not mistaken, so no way to precompile them all.

Our only solution we see is, to import the whole landscape into the demo level, but our world is large…
Also the player may need to recompile, when he changes graphics settings.

So… let’s see. Will get back here when we found a solution. Thank you for your time!