UGUI wastes huge amounts of CPU time when calling Camera.Render()

Steps to reproduce:

  • Create a screen space (camera) canvas and fill it with lots of UI elements. Make sure it’s set to render via the main camera.
  • Create a second camera, disable it, and set its culling mask to ‘None’
  • Add a script that has an OnRenderObject method which calls ‘Render()’ on the disabled camera.
  • Profile the scene.

You’ll see something like this:

6996590--826562--upload_2021-4-1_11-58-34.png

UGUI will go to all the trouble of culling and batching the entire contents of the UI, even though the canvas is explicitly targeted at a different camera and is in a layer excluded from the second camera’s mask.

We are using a number of cameras to render elements of our UI on demand, and this bug is killing us. Every camera we render triggers a complete rebatching of the entire UI, even though none of it will ever be drawn through that camera.

FYI: we’ve managed to concoct a workaround: instead of calling Camera.Render() (which was handy because it allowed us to easily have multiple copies of a 3D element present on the same screen), our UICamera script now clones the ‘picture in picture’ camera as often as is necessary and lets it be rendered in the usual way, saving us (and this is not hyperbole) 200ms of busywork per frame.