Poor Slate3D Performance

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:

  1. Create a new project with an empty map;
  2. Create a widget blueprint with a custom size, say, 512*512;
  3. 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;
  4. Place an empty actor on the map, preferably right in front of the default PlayerStart;
  5. 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;
  6. Save everything, close the editor and run the map again with -game -vr argument;
  7. 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!

After a deeper research we finally found out that it’s not Slate3D who should take responsibility. The whole GPU profiling is inaccurate or nonsense, if the renderer has been capped to a certain frame rate while the actual rendering workload is low. Say, if your game is capped (by VSync or whatever) to 60 fps and the actual frame render time is lower than 1/60s (16.7ms), part of the spare time could be counted as cost or overhead to Slate3D, or sometimes HZB or other innocents.

I think this should be addressed as a bug of the GPU profiler.

We’re facing this issue with 4.14 migration to 4.15. The Slate3D suddenly goes up very high.

However in our cast the Slate3D slowly rises over time as if it’s memory leak. I’m not sure if it’s due to cap , because in our case we started off with 60fps and then keeps dropping until 38 or so. with majority of it coming from Slate3D . Going up to 13ms at max. we hardly have any slate3D displayed.

I dont have much knowledge about GPU processing and profiling, but I started some simple profiling as explained here in the docs (still have no clue what most of it means) but the thing that sprung in my eyes right away is that Slate3D is given as the most expensive item in my render task list (3-4 times more than the next item) and all I have are about 10 small posters in the world with text on them. When I remove them the Slate3D number goes away but the overall rendertime does not change
I’m using UE 4.15 too, I didn’t do any profiling in earlier versions so I dont know if it changed