damageScreen() in UnityScreen::nuxDamageCompiz() severely hurts Unity performance

Bug #1080947 reported by Daniel van Vugt
72
This bug affects 16 people
Affects Status Importance Assigned to Milestone
Unity
Fix Released
High
Sam Spilsbury
6.0
Won't Fix
High
Unassigned
unity (Ubuntu)
Fix Released
High
Unassigned

Bug Description

There's a call to damageScreen in UnityScreen::nuxDamageCompiz that I had to put there to work around rendering bugs when we did the GLES port. It has a significant impact on performance however and should be removed ASAP, replaced with something like the old version of UnityScreen::nuxDamageCompiz.

I think this is causing bug 1039942, and probably others too.

Tags: multimonitor

Related branches

Changed in unity (Ubuntu):
status: New → Triaged
importance: Undecided → Medium
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

Tagged multimonitor. Calling damageScreen is a big bottleneck if you have unityshell loaded and it has to redraw on multiple monitors.

tags: added: multimonitor
Changed in unity:
assignee: Daniel van Vugt (vanvugt) → Sam Spilsbury (smspillaz)
status: Triaged → In Progress
Revision history for this message
Sam Spilsbury (smspillaz) wrote :

Hmm, would you accept a fix to this if it worked in the normal case, but had a slight feedback loop in the case where GLX_EXT_buffer_age was supported ?

The best way to handle this problem is to add support for geometry clipping to nux (eg, give nux a list of rectangles, and when it draws textures, it will determine the correct vertices + texcoords for the drawn textures to remain within those rectangles). However, adding support for geometry clipping to nux is not trivial. Worth doing if we can, but we need to talk with the relevant people about that.

Currently, my approach is to give nux the damage region, and have it determine which BaseWindows need to be presented to the screen. We also get back that list, and ensure that the damage region covers that area too (to prevent overdraw). However, that approach is slightly flawed when the backbuffer is partially defined, as we have to mark the nux areas as damaged, and then that feeds back into the next time we redraw, when we just re-present the nux windows again because their area was damaged on a previous frame.

(Sorry, I can't make that any more terse, its a complicated problem and I've been looking into it for days).

Revision history for this message
Sam Spilsbury (smspillaz) wrote :

To clarify - the feedback loop is a worse-case that is still better than the best case that we have now. It doesn't cause constant redraws, rather, it just means that the nux windows will always be drawn to the screen every time a compiz window updates. The cost is not that bad - as it is two draw calls at the most.

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

I would suggest first remove the damageScreen and reintroduce the old code that it replaced. Then you will have solved this bug and probably only need to solve some flickering which the damageScreen call was introduced to work around.

No changes to Nux should be required.

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

In fact, the flickering might be fixed now. In which case it's just a matter of re-introducing the old code that used to be below the #else.

Revision history for this message
Roman Yepishev (rye) wrote :

I am from bug 1100456 and I have to say that it does not look like unity-only issue. Today I half-upgraded to the latest and greatest packages and got unityshell failing to start (and compiz depending on compiz-core that is not yet pushed to the archives) so I got a compiz-only session.

Running http://paste.ubuntu.com/1538829/ still tells me that any screen redraw triggers a full-screen XDamage event even when no unityshell is running.

Are you sure bug 1100456 is a duplicate of this one?

Revision history for this message
Sam Spilsbury (smspillaz) wrote : Re: [Bug 1080947] Re: damageScreen() in UnityScreen::nuxDamageCompiz() severely hurts Unity performance

On Thu, Jan 3, 2013 at 4:26 PM, Daniel van Vugt
<email address hidden> wrote:
> I would suggest first remove the damageScreen and reintroduce the old
> code that it replaced. Then you will have solved this bug and probably
> only need to solve some flickering which the damageScreen call was
> introduced to work around.
>
> No changes to Nux should be required.
>

I have already done this in my experimental unity and nux branches.

No, the changes are not as simple as they might seem.

Calling WindowThread::RenderInterfaceFromForeignCmd renders the WHOLE
interface regardless of the damage region. It does this by painting a
bunch of textures back on-screen. Rendering outside the damage area is
always overdraw, so there needs to be special code to account for
that.

Please read my comments carefully before responding to them.

> --
> You received this bug notification because you are a bug assignee.
> https://bugs.launchpad.net/bugs/1080947
>
> Title:
> damageScreen() in UnityScreen::nuxDamageCompiz() severely hurts Unity
> performance
>
> Status in Unity:
> In Progress
> Status in “unity” package in Ubuntu:
> Triaged
>
> Bug description:
> There's a call to damageScreen in UnityScreen::nuxDamageCompiz that I
> had to put there to work around rendering bugs when we did the GLES
> port. It has a significant impact on performance however and should be
> removed ASAP, replaced with something like the old version of
> UnityScreen::nuxDamageCompiz.
>
> I think this is causing bug 1039942, and probably others too.
>
> To manage notifications about this bug go to:
> https://bugs.launchpad.net/unity/+bug/1080947/+subscriptions

--
Sam Spilsbury

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

Roman,

I have unduplicated your bug and added more information.

Revision history for this message
Scott Deagan (scott-deagan) wrote :

I'm here from bug 1007857. I have tried to make a video of the problem, but the stuttering doesn't look that bad in the video. I think my phone camera doesn't record at a high enough refresh rate:

http://www.youtube.com/watch?v=T9Q879m9J2k

In short, when I run on a single monitor (a Dell U2711 at 2560x1440) using either an nVidia GTX 460 or AMD Radeon 7870, dragging windows around near the top bar or the Unity Launcher results in very stuttery movement (it's not fluid).

The problem is not noticeable on my laptop which runs an Intel HD 4000 integrated graphics. With the Intel HD 4000 everything feels buttery smooth and super responsive. I did, however, find that with two monitors (one set to 1080p, the other to 1440p) that some animations were jerky (such as SuperKey + W and SuperKey + S).

Just adding my observations here in case it helps somehow.

Changed in unity:
importance: Medium → High
Changed in unity (Ubuntu):
importance: Medium → High
Stephen M. Webb (bregma)
Changed in unity:
milestone: 7.0.0 → 7.0.1
Stephen M. Webb (bregma)
Changed in unity:
milestone: 7.0.1 → 7.1.2
Stephen M. Webb (bregma)
Changed in unity:
milestone: 7.1.2 → 7.2.0
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :

Fix committed into lp:unity at revision None, scheduled for release in unity, milestone 7.2.0

Changed in unity:
status: In Progress → Fix Committed
Revision history for this message
Launchpad Janitor (janitor) wrote :
Download full text (18.5 KiB)

This bug was fixed in the package unity - 7.1.2+14.04.20140214.1-0ubuntu1

---------------
unity (7.1.2+14.04.20140214.1-0ubuntu1) trusty; urgency=low

  [ Sebastien Bacher ]
  * use unity-control-center by default.
  * lists keybinding in unity-control-center. (LP: #1271710)

  [ Brandon Schaefer ]
  * Bump to new libnux from this branch:
    https://code.launchpad.net/~brandontschaefer/nux/xim-preedit-
    support.
  * Adds Super+L to lock the screen, while keeping the older shortcut
    around in g-s-d (Ctrl+Alt+L). (LP: #830709)
  * Do not open the dash/hud on a monitor with a top most window that is
    fullscreen. (LP: #1267210)
  * Implement an EMConveter. This way with default settings such that
    DPI = 96.0f, and font_size = system font size. We can get the
    correct EM value for any pixel size. Once we have the correct EM
    value for any pixel size, the DPI value can be adjusted to the
    current logical one. From here, you can now get the correct pixel
    size based from of the EM value for the logical DPI of the screen.
  * Refactor EMConverter API. Now all thats needed is int
    ConvertPixels(int pixel); This will calculate the correct pixel size
    based on the DPI and font size.
  * Testing that the ibus anthy tests could possibly be causing strange
    issues on the nvidia machine. So skipping them to test if tihs is
    the source of the error.
  * Add Pt to Px function to em converter.
  * Move EMConverter over to unity settings.
  * Add multi monitor support for EMConverter in unity settings. Now you
    can grab a specific converter per monitor.
  * Simple RawPixel class. It adds 2 define literals, ex: 10_em,
    10.0_em. From there it turns them into raw pixels. RawPixels have CP
    (CovertPixel) function which takes in an EMConverter that allows you
    to use a converter specific to a monitor to convert the raw pixel to
    the correct value.

  [ Marco Trevisan (Treviño) ]
  * Don't re-present all of our windows on every frame. Only do that if
    damage intersects it. Use the new APIs exposed by compiz and nux to
    intelligently determine which windows need to be presented per-frame
    and only register damage for those windows. This fixes two things:
    1. BaseWindows being redrawn from scratch every time damage was
    registered over them. That was incorrect and should only be done in
    the case of background blurs. 2. BaseWindows being drawn to the
    screen on every frame, regardless of whether or not they needed to
    be. Now they will only be drawn if some damage intersects beneath
    them. Note that unity will expand the damage region to accomadate
    the base window since nux does not support geometry clipping. So if
    there is a partial intersection of the launcher for example, the
    area of the screen which contains the launcher will be re-painted
    (but the launcher itself won't be redrawn, just its texture) (LP:
    #1080947). (LP: #1080947)
  * Convert compiz regions / rects to nux::Geometry's and back easily.
  * UnityScreen: remove the useless and expensive gl{Push,Pop}Attrib
    calls For some reasons this code was copied by the opengl plugin as
    a workaround to fix the s...

Changed in unity (Ubuntu):
status: Triaged → Fix Released
Revision history for this message
Stephen M. Webb (bregma) wrote :

Fix Released in Unity Unity 7.2.0.

Changed in unity:
status: Fix Committed → Fix Released
Revision history for this message
Robert Siemer (robert-siemer-launchpad-net) wrote :

MC Return said bug 784055 is rooted here.

https://bugs.launchpad.net/indicator-multiload/+bug/784055/comments/13

That bug is not fixed. I can confirm this for 14.04 trusty. – If MC Return is right, this bug isn’t fixed either.

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Duplicates of this bug

Other bug subscribers

Remote bug watches

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