Mir

Compositing is triggered continously and needlessly when there are occluded surfaces with available buffers

Bug #1418081 reported by Alexandros Frantzis
8
This bug affects 1 person
Affects Status Importance Assigned to Milestone
Mir
Fix Released
High
Daniel van Vugt
mir (Ubuntu)
Fix Released
High
Unassigned

Bug Description

Because of recent changes in the way the MultiThreadedCompositor is triggered (or rather retriggered) [1], when the DisplayBufferCompositor doesn't render (e.g. because it's occluded) a non-hidden surface that has available buffers, compositing is retriggered continuously at full rate, even when nothing else changes on screen.

To test this, run the proving server:

$ sudo bin/mir_proving_server --compositor-report log

then start a client and drag the client offscreen. The compositor log should report that the compositor has a frame rate of max(client frame, FDP) (FDP=value related to our frame droping policy). However, you will see that it's instead rendering at 60FPS.

As an extreme (but not unusual) example of how problematic this behavior can be, perform the following:

1. Change an example client to render at ~1 FPS (e.g. add sleep(1) in it's main loop).
2. Perform the previous experiment with that client

When the client surface is visible, the compositor is triggered at a rate of 1FPS. The same should be true when the surface is dragged off screen, but instead we get a full compositing rate of 60FPS.

[1] https://code.launchpad.net/~vanvugt/mir/fix-buffers_ready_for_compositor/+merge/247124

Related branches

summary: Compositing is triggered continously and needlessly when there are
- occluded surfaces
+ occluded surfaces with available buffers
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Unfortunately this sounds kind of right.

We failed to consume all buffers last frame, and it's quite possible that the shell has changed something that allows them to be consumed on the next. So the right answer is indeed to schedule a frame immediately.

To solve this for everyone we would probably have to distinguish between the _reasons_ for a buffer not getting consumed. Starts to sound messy.

Revision history for this message
Chris Halse Rogers (raof) wrote :

Wouldn't it be nice if the scenegraph lived in Mir so we could tell whether or not the changes required recompositing? :)

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

I think for the complex composited desktop case, this is OK. It's perfectly fine performance wise on a desktop if you have a window producing new frames that the compositor wakes up.

For mobile devices, this would be a non-issue. Because Ubuntu-touch freezes them with SIGSTOP so they can't produce new frames while occluded.

Changed in mir:
importance: High → Medium
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Interestingly the logic is in the scene graph right now (SurfaceStack is our implementation of Scene) so we could wire something up maybe.

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Hmm, we could modify frames_pending() to not count any surface that is occluded. That would resolve alf's concerns, but I'm not totally sure it's a good idea to make a special case of occlusion. If someone writes a shell that changes its view of surfaces without changing the Scene, then "fixing" this bug would cause problems of visible lag and even indefinite freezes.

I think we're better off declaring this not-a-bug. But I also think it could be easy to fix if necessary.

Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

> I think for the complex composited desktop case, this is OK. It's perfectly fine performance wise on a desktop
> if you have a window producing new frames that the compositor wakes up.

The occluded surface doesn't need to continuously produce frames. As long as a surface has an available frame and is not rendered (e.g. it's occluded), the compositor will composite at full speed (60FPS).

> For mobile devices, this would be a non-issue. Because Ubuntu-touch freezes them with SIGSTOP so they can't produce
> new frames while occluded.

For the same reason mentioned above, SIGSTOP doesn't help.

Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

> The occluded surface doesn't need to continuously produce frames. As long as a surface
> has an available frame and is not rendered (e.g. it's occluded), the compositor will
> composite at full speed (60FPS).

And for this reason, this bug constitutes an important performance and power consumption regression.

Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

I think this could be quite serious:

I'm not sure if USC currently works like this but consider:

The greeter starts,
U8 starts and is occludes the greeter.
Around this time the greeter provides a new buffer that doesn't get rendered as it is occluded.
Now there is always an unconsumed buffer in the scene, so compositing never stops.

It is far easier to get scenarios like this on a "desktop" and that is a big waste of resources, on a laptop we don't want to drain batteries like this but on a phone battery this behaviour is deadly.

AFAICS the "query" needs to check only the surfaces /that would be rendered/ and once upon a time we had logic that did this during the compositing pass. (Occlusion is indeed only a special case of surfaces that are not rendered - and it would be good to address the general case.)

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Ignoring the fact that I feel the back-and-forth of occlusion flagging feels like a kludge, I think I could "fix" this easily.

But I would much rather we treated compositing as a one-way activity where the scene (model) is viewed by the compositor (view). Allowing the compositor to touch the scene with occluded() as it does is a bit messy.

Changed in mir:
assignee: nobody → Daniel van Vugt (vanvugt)
Changed in mir:
importance: Medium → High
milestone: none → 0.11.0
status: New → In Progress
milestone: 0.11.0 → 0.12.0
Revision history for this message
Alan Griffiths (alan-griffiths) wrote :

"Allowing the compositor to touch the scene with occluded() as it does is a bit messy."

Totally agree.

At some level the compositor "knows" which surfaces went into compositing. It ought to be able to determine whether these have unrendered surfaces without a mutating "touch".

Revision history for this message
Alexandros Frantzis (afrantzis) wrote :

> > "Allowing the compositor to touch the scene with occluded() as it does is a bit messy."
>
> Totally agree.
>
> At some level the compositor "knows" which surfaces went into compositing. It ought to be able to determine
> whether these have unrendered surfaces without a mutating "touch".

This will happen when we get a smarter and richer scene(graph) that can represent whatever a shell may want display (in terms of client surfaces; think effects like expose, live previews etc) and which can give the DB compositors a final list of renderables to render.

That being said, the current mechanism (which queries on available surface buffers) doesn't fail because the compositors can "touch" the scene, but because the compositors are allowed to not render the surfaces we give them. Even if we had a better scene, we would need to guarantee that compositors actually use the surfaces we give them for the current mechanism to work.

Revision history for this message
Kevin DuBois (kdub) wrote :

I do think the new problem brought up in this bug needs addressing, just as the lingering frames also needed addressing.

I would be okay with Alexandros's 'smarter and richer' scene, however, its a bit tricky to limit when we shove the final list of renderables over to the compositors. (eg, we don't want a flurry of renderables being sent to the compositors to sort out when something damages the scene).

I think that the concept of "producing damage in the scene" and "consuming damage in the compositors" clears this up nicely. I also think that we don't have, and haven't had the concept of damage in the proper location in the codebase. (and, prior to and after fix-buffers-ready-for-compositor). We previously had the surfacestack try to track damage without the input of the BufferQueues, and now we're trying to have the surface stack wake up the compositors, and the BufferQueues determine when the compositor goes to sleep.

So, the scene (via the observers, in the current architecture), notifies the compositors that it has been damaged ("produces damage"). The compositor wakes up and calls scene_elements_for(), and "consumes a damage". This has a nicer "produce/consume" model than a "wakeup-and-run-until" that we currently have. The scene can keep producing more damage as it sees fit, and the compositor has to consume all the produced damage before it goes to sleep. (obviously, the damage is a per-display concept, but we already have the concept of registering and deregistering compositors with the scene, so this is okay)

Revision history for this message
Daniel van Vugt (vanvugt) wrote :

BTW, please keep the "rich scene graph" discussion separate. We don't have such a thing yet and Unity8-dev has (this week) expressed a preference that we don't. They'd rather we just enrich SurfaceStack slightly, because that's nice and independent of the compositing method, everyone's more free to build shells in their own ways.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

Fix committed into lp:mir at revision None, scheduled for release in mir, milestone 0.12.0

Changed in mir:
status: In Progress → Fix Committed
Kevin DuBois (kdub)
Changed in mir:
milestone: 0.12.0 → 0.13.0
no longer affects: mir/0.11
Changed in mir (Ubuntu):
importance: Undecided → High
status: New → Triaged
Changed in mir:
status: Fix Committed → Fix Released
Revision history for this message
Launchpad Janitor (janitor) wrote :

This bug was fixed in the package mir - 0.13.1+15.10.20150520-0ubuntu1

---------------
mir (0.13.1+15.10.20150520-0ubuntu1) wily; urgency=medium

  [ Cemil Azizoglu ]
  * New upstream release 0.13.1 (https://launchpad.net/mir/+milestone/0.13.1)
    - ABI summary: No ABI break. Servers and clients do not need rebuilding.
      . Mirclient ABI unchanged at 8
      . Mircommon ABI unchanged at 4
      . Mirplatform ABI unchanged at 7
      . Mirserver ABI unchanged at 31
    - Bug fixes:
      . Can't load app purchase UI without a U1 account (LP: #1450377)
      . Crash because uncaught exception in mir::events::add_touch (LP: #1437357)

 -- CI Train Bot <email address hidden> Wed, 20 May 2015 21:20:15 +0000

Changed in mir (Ubuntu):
status: Triaged → Fix Released
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.