Hi everyone,
Recently we found that using WidgetComponent in certain circumstances (specifically, under VR environment) could drastically lower the GPU performance. After two days’ tracking, we narrowed the issue down to the RHICmdList.DrawIndexedPrimitive calls in SlateRHIRenderingPolicy.cpp. These calls simply push several draw calls to the GPU, but can deliver an unacceptable pressure to it. In our game, all the WidgetComponents are supposed to be rendered within ~0.1 milliseconds, which is actually possible if we don’t run in VR mode; but in VR mode, they need more than 10 milliseconds to be rendered. I understand there can be performance drawbacks in VR mode, but a difference of ~100 times is really unbelievable.
Minimum Reproducible Scenario
We created a minimum scenario to reproduce the issue. Here are the steps:
- Create a new project with an empty map;
- Create a widget blueprint with a custom size, say, 512*512;
- Place the following widgets into the designer: a Text, an Image and a canvas with another Text in it. All the widgets can have their default values, and can be placed at random locations;
- Place an empty actor on the map, preferably right in front of the default PlayerStart;
- Add a widget component to the empty actor, and set the Widget Class to the widget blueprint we just created. Rotate the widget component by 180 degrees around the Z axis so it will be facing the PlayerStart;
- Save everything, close the editor and run the map again with -game -vr argument;
- Use the stat gpu command in the console, and you will see Slate3D consumes a ridiculously high GPU time, which, on my GTX1070 machine, can be over 1 milliseconds, or 0.5 milliseconds on a GTX1080 machine.
Facts and Thoughts
- Test environment: i7 4970/GTX 1070 or GTX1080/32GB RAM/Windows 10 Professional/GeForce Game Ready Driver 378.66
- The widgets created in step 3 are delicate. If you remove any of them, or simply move the second Text out from the Canvas, the performance cost will drop to a negligible value. However, such widget combination is really common and unavoidable in practices;
- The performance impact can happen even if the game is not running under VR mode, but with SteamVR running in the background. Uninstall SteamVR and run the game again, the impact disappears;
- We tested the case on both HTC Vive and Oculus Rift CV1, both have the issue;
- We tested the case in engine version 4.14.0 (nVidia VRWorks variant) and 4.15.0(official version, started from the launcher), both have the issue;
- Place duplicates of the actor with widget component only increase the GPU time by a very little pinch. There seems to be an inherent overhead in certain implementation of Slate3D;
- The performance impact could increase if GPU workload gets heavier. For example, if we put some (hundreds of) meshes into the test scene, resulting a ~10M triangles, the Slate3D GPU time will increase to 3 milliseconds
- We tried to capture frames to do some further analysis, unfortunately all the tools we have refuse to work (dxcap and nSight), we will try other tools later and report here once we have any progress.
Any thoughts would be appreciated!