|
|
|
**Table of Contents**
|
|
|
|
|
|
|
|
[[_TOC_]]
|
|
|
|
|
|
|
|
|
|
|
|
Performance is key for all VR applications, and it's not always easy to debug and find possible issues with Unreal. However, there are plenty of resources out there to help you find out exactly why your Unreal application is running slow, and what you can do to meet that harsh 90 fps target for HMDs.
|
|
|
|
|
|
|
|
## Do I even have a performance problem?
|
|
|
|
|
|
|
|
Unreal itself gives a few [stat commands](https://docs.unrealengine.com/5.0/en-US/stat-commands-in-unreal-engine/) that display performance related stats directly in the app.
|
|
|
|
These should be your first indicator of how your program is performing.
|
|
|
|
However, those aren't always representative as the HMDs often do forced reprojection and frame syncing. The most accurate way to get your application's frame timings is through the HMD vendor's debug software:
|
|
|
|
|
|
|
|
- [Oculus Debug Tool](https://developer.oculus.com/documentation/native/pc/dg-debug-tool/?locale=de_DE)
|
|
|
|
- [SteamVR Frame Timings](https://developer.valvesoftware.com/wiki/SteamVR/Frame_Timing), [Unreal Doc](https://docs.unrealengine.com/en-US/Platforms/VR/SteamVR/ProfilingPerf/index.html)
|
|
|
|
|
|
|
|
If those profiling tools show no issues - great! If they do, debugging gets a bit iffy.
|
|
|
|
|
|
|
|
### Unreal Testing and Optimizing Reference
|
|
|
|
|
|
|
|
The Unreal docs regarding performance are quite extensive and an overview can be found here:
|
|
|
|
|
|
|
|
- [Unreal Testing and Optimizing Reference](https://docs.unrealengine.com/5.0/en-US/testing-and-optimizing-your-content/)
|
|
|
|
- [Optimizing and Debugging Projects for Real-Time Rendering](https://docs.unrealengine.com/5.0/en-US/optimizing-and-debugging-projects-for-real-time-rendering-in-unreal-engine/)
|
|
|
|
|
|
|
|
### Disabling ASW/Reprojection
|
|
|
|
|
|
|
|
To get correct application frame timings, disabling reprojection/warping methods is the first step towards accurate readings.
|
|
|
|
|
|
|
|
- For Oculus, this is fairly straightforward: Open above mentioned debug tool and set Asynchronous Spacewarp to Disabled.
|
|
|
|
- For SteamVR, this is more tricky - Open SteamVR, go to Developer -> Debug Commands and use the async_mode_toggle command while the application is running. ([Screenshot](https://i.imgur.com/T4xmpdH.png))
|
|
|
|
- These change a lot depending on which version of Oculus and SteamVR are installed, so take it with a grain of salt.
|
|
|
|
|
|
|
|
Then, you should be able to get reasonably accurate frame timings from Unreal or 3rd party stats commands and profilers.
|
|
|
|
|
|
|
|
## Profilers
|
|
|
|
|
|
|
|
The [Unreal XR Profiling documentation](https://docs.unrealengine.com/5.0/en-US/xr-performance-and-profiling-in-unreal-engine/) is growing bit by bit, but fairly unstructured - take a look there, but some of the features might require Unreal 5.
|
|
|
|
|
|
|
|
Personally, I can really recommend [Unreal Insights](https://docs.unrealengine.com/5.0/en-US/unreal-insights-in-unreal-engine/), especially because it allows you to export custom profiling stats in your own application code. See the documentation for more examples.
|
|
|
|
|
|
|
|
For GPU Debugging, [RenderDoc](https://docs.unrealengine.com/en-US/Engine/Performance/RenderDoc/index.html) is absurdly good in general, but it won't give you perfectly accurate Draw Call timings. It's very good to debug your shader complexity and general rendering pipeline states, not just for performance reasons.
|
|
|
|
|
|
|
|
Additionally, Intel themselves published a very good profiling tutorial series for Unreal specifically as well, [Part 1/4 can be found here](https://software.intel.com/content/www/us/en/develop/articles/unreal-engine-4-optimization-tutorial-part-1.html).
|
|
|
|
|
|
|
|
## Quick performance improvements through simple settings changes
|
|
|
|
|
|
|
|
The default settings for Unreal scenes are not optimized for performance, which becomes clear when running the Default Scene in VR and comparing it to e.g. Unreal's own VR Template. The difference for me was something around 8ms (Default) to 4ms (VR Template) frame timings. [There are a few simple adjustments to make to get better performance without many drawbacks](https://docs.unrealengine.com/en-US/Platforms/VR/DevelopVR/VRPerformance/index.html):
|
|
|
|
|
|
|
|
- Enable Instanced Stereo in your Peoject Settings
|
|
|
|
- Disable any post processing effects you don't need in Project Settings or via an unbounded `PostProcessVolume`.
|
|
|
|
- Often, Forward Shading is recommended. This is something that is very application specific and not a guaranteed performance gain, so try it out with above profilers and see if it gains you any milliseconds.
|
|
|
|
- [Scalability settings](https://docs.unrealengine.com/5.0/en-US/scalability-in-unreal-engine/): For some reason, Unreal gives a lot of scalability and performance options via .ini files that are not mentioned *anywhere* in the Project Settings. The simplest way to to achieve a way better performance is to just copy the `DefaultScalability.ini` from the Unreal VR Template into your project's config directory.
|
|
|
|
- General config settings: Additionally to the Scalability settings, Unreal published the settings used in the VR Showdown demo [here](https://docs.unrealengine.com/en-US/Platforms/VR/DevelopVR/ContentSetup/index.html), alongside some more performance tips. The page is fairly outdated tho, so take it with a grain of salt.
|
|
|
|
- [Turn on Blueprint Nativization](https://docs.unrealengine.com/5.0/en-US/nativizing-blueprints-in-unreal-engine/): If you're using a lot of Blueprint code, Nativization compiles those Blueprints to C++ instead of running them in the VM. This can gain *a lot* of CPU performance, depending on your Blueprints. However, it also might break some things (especially with UI related stuff) so just try it and see what it results in.
|
|
|
|
|
|
|
|
## Improving your application code
|
|
|
|
|
|
|
|
### Todo
|
|
|
|
|
|
|
|
- ParallelFor
|
|
|
|
- Async execution
|
|
|
|
- TickGroups
|
|
|
|
- TRACE_CPUPROFILER_EVENT_SCOPE(TEXT("UMyActor::MyFunction"))
|
|
|
|
- UE426/427/5 differences
|
|
|
|
|