PSO Cache: for iOS Devices

Hello everyone, I hope y’all fine.

I am creating a small game for a customer, it is feature-ready and the only thing left to do is optimizing the first launch of the game, let me explain:
I’m testing a shipping packaged game (not development shipping) from TestFlight, when I do a fresh intall of the game, it start stuttering and almost freezing. After some time, game runs super smooth and it is very optimized: I profiled it, did Unreal Insight, nothing weird or taking too much CPU/GPU computation. On second launch, it is super fast.

The more I go deep into the level, the less stutters, so I thought it is surely related to the fact that the game is “unpacking” / loading all the needed assets/shaders when it meets it. My problem seems just related to the first launch/meeting a new texture or something.

I did some researches and I found this article about PSO Caching Optimizing Rendering With PSO Caches in Unreal Engine | Unreal Engine 5.1 Documentation

I tried following this doc but I got stuck and got confused about things (later I will ask some questions). I got stuck at step 2 where it tells me to go to Saved/CollectedPSOs folder to get those recorded files ingame, but I couldn’t find any. Then I asked myself:

1 - Do I need an iOS device to record the PSO files?
2 - Or is it ok to record them on my PC and then use them for the iOS Package (in editor? in simulation?) ?
3 - If I need to do it on an iOS device, where will I find the PSO files saved? Or maybe connect my iPhone to my PC and launch it from there?

I searched for a written tutorial but I couldn’t find something that was ios related, they were different/not the same Unreal version and for Android.

So please, does anyone have a solution / written tutorial for this? Seems like this subject is not interesting at all, I litterally found only 3 videos about PSO caching and on older versions UE4 and for Android, not iOS. This is so weird, maybe I’m missing something and this procedure is outdated already??

Otherwise, what should I do to optimise the first launch on iOS devices?

If needed, I can try to add information.

Thank you for your time!

I know this is an old topic, but I came across it and thought I’d post since I’ve been doing some related work recently, hopefully it helps someone.

I would say PSO caching is pretty important most shipped games, as you’ve seen the stuttering without it can be pretty bad if you have many shader variants (and it’s very easy to end up with a lot). On mobile, I would add that generally the tradeoff is that your startup time will be longer, assuming you choose to precompile the whole thing on startup, so keep that in mind as well.

To answer your broad questions:

1 + 2. To generate PSO caches for a given platform (+ graphics API, for example Android GLES / Android Vulkan), you must use the corresponding device. So yes, you have to have an iOS device to generate PSO caches for iOS. Incidentally, for anything involving iOS I personally highly recommend having a Mac available, some parts of the process get much more annoying without one.
3. The saved pipeline cache files will be located in the app bundle’s data folder, under Saved/CollectedPSOs (you can see this in PipelineFileCache.cpp in the engine’s source).

To actually retrieve these from the iOS device, you have to be able to get the contents of the app bundle from it. On macOS you would do this from Xcode - in the Devices window, your app should be listed in the installed apps list on your development device, and you can right click it and download the app container back to your Mac. It will come in as an .xcarchive file or similar, you can just change the extension to .zip, unzip it, and the resulting folder will contain all the app’s files, including the folder where the PSO cache files are. There are also some paid 3rd-party apps, like iMazing, that let you explore the app packages and get the files as well.

On Windows, I believe there are some 3rd party apps that can also pull these archives, though I’m not familiar with them.

All that said, the bigger problem, and the reason you’ll want a Mac, is the first and last parts of the process. The first is to have your game generate the PSO cache file in the first place, and the last part is to generate on your development machine the final cache file with the Unreal commandlet, which the engine will use to make the on-device pipeline state cache the next time you make a build.

The first part requires running the game with the -logpso command line switch, and running the game on iOS with command line switches is possible with only two ways I know of:

  1. Running with xctrace - this is the only way I know of to launch an iOS app with extra command line args, I have searched and searched and never found any other way. On a Mac with all the dev tools installed, you can run xcrun xctrace record --template 'Activity Monitor' --device <your device ID> --launch -- 'your.app.bundle.name' -logpso [any other args you want]. Note that running with command line args isn’t actually the purpose of xctrace - it’s meant for debugging etc, we just happen to be able to launch with args this way. The trace file it will generate is useless for our purposes and can be ignored.
  2. Using UECommandLine.txt (or UE4CommandLine.txt if you’re on UE 4), details here: https://dev.epicgames.com/documentation/en-us/unreal-engine/command-line-arguments-in-unreal-engine

#1 can only be done on a Mac, and #2 can be a pain; I’m not sure if it’s possible to add the command line file to an existing build, I think you pretty much have to add it to your project and then generate a whole new build.

As for the last bit, the commandlet, this also does not technically require a Mac, but it’s much easier if you have one. Creating a build generates .shk files for the platform being built and places them in the Saved/Cooked/[Platform]/[YourProject]/Metadata/PipelineCaches folder. The commandlet needs those files, so if you’re generating your iOS builds elsewhere, like a build farm etc, you’ll need to retrieve that somehow (or run the commandlet on that build server). This will create the stable pipeline cache file you can then use when making new builds, as on Android / PC.