Mir

Full screen (bypassed) surfaces (e.g. GLMark2Test) are missing frames and appear to freeze or judder with swap interval 0

Bug #1379685 reported by Daniel van Vugt on 2014-10-10
8
This bug affects 1 person
Affects Status Importance Assigned to Milestone
Mir
Fix Released
Medium
Daniel van Vugt
mir (Ubuntu)
Medium
Unassigned

Bug Description

I'm observing missing client frames when swap interval is set to zero.

Test case (1):
https://code.launchpad.net/~vanvugt/mir/wacky/+merge/237907

Test case (2):
sudo bin/mir_performance_tests
Expected: Perfect smoothness
Observed: Constant slight visible judder during all the animations.

Related branches

Changed in mir:
assignee: nobody → Daniel van Vugt (vanvugt)
Daniel van Vugt (vanvugt) wrote :

The problem appears to be our new(ish) drop_frame implementation:

void mc::BufferQueue::drop_frame(std::unique_lock<std::mutex> lock)
{
    auto buffer_to_give = pop(ready_to_composite_queue);
    /* Advance compositor buffer so it always points to the most recent
     * client content
     */
    if (!contains(current_compositor_buffer, buffers_sent_to_compositor))
    {
       current_buffer_users.clear();
       void const* const impossible_user_id = this;
       current_buffer_users.push_back(impossible_user_id);
       std::swap(buffer_to_give, current_compositor_buffer);
    }
    give_buffer_to_client(buffer_to_give, std::move(lock));
}

The issue is that ready_to_composite_queue.size() == 1, somehow, and so we're actually dropping the newest frame. The complicated swapping logic in the middle (which seems to be an attempt to avoid the problem) appears to be doing nothing, or simply not working.

Changed in mir:
status: New → Triaged
importance: Undecided → High
Daniel van Vugt (vanvugt) wrote :

And ready_to_composite_queue.size() == 1, because buffers_sent_to_compositor.size() == 2.

And that is because the compositor is holding buffers across frames. Which is because it's full screen -- bypass!

So the answer is BufferQueue is behaving as well as it can. But if you want to avoid out-of-order frames and have bypass support then you need quad buffers :P

Actually, now I remember this is a problem I discovered in lp:~vanvugt/mir/double ... if you had framedropping and bypass then real buffer demand reached 4. If you enable bypass with framedropping and only have 3 buffers then you'll end up dropping your newest frame.

There is an alternative solution to quad-buffering though - Drop the oldest frame which *might* still be bypassed. Worst case is you end up tearing.

summary: - Missing frames/out of order with swap interval 0
+ Full screen (bypassed) surfaces are missing frames/out of order with
+ swap interval 0
Changed in mir:
importance: High → Medium
assignee: Daniel van Vugt (vanvugt) → nobody

A second alternative solution is to let bypass tear if framedropping is enabled. Then it doesn't need to hold any buffer reference, just reset the CRTC each frame.

Alexandros Frantzis (afrantzis) wrote :

> There is an alternative solution to quad-buffering though - Drop the oldest frame which *might* still be bypassed.
> Worst case is you end up tearing.

> A second alternative solution is to let bypass tear if framedropping is enabled. Then it doesn't need to hold any
> buffer reference, just reset the CRTC each frame.

It's acceptable to have tearing with swap interval 0, and tearing is surely preferable to having out of order frames. All else being equal, we should prefer the solution that leads to the best visual experience, which could be either doing our best to minimizing tearing, with the risk of being inconsistent about it, or providing consistent tearing.

"Best visual experience" is easily achieved if we just intelligently scale up to quad-buffers when required. Then you never lose any frames and never tear. I will have to revive the aforementioned "double" branch and reintroduce the demand heuristic.

It's not just bypass either. Multi-monitor can lead to the same situation with frame dropping surfaces. It's quite plausible that two different compositor buffers are being held, resulting in only one left over for the client and so the newest frame gets dropped.

Dropping the newest frame on a surface that's rendering continuously is just a degradation in visual quality. But in a render-on-demand app, it can be catastrophic - resulting in an apparently frozen window with no new frames displayed for an unpredictably long time.

summary: - Full screen (bypassed) surfaces are missing frames/out of order with
- swap interval 0
+ Full screen (bypassed) surfaces are missing frames and appear to freeze
+ with swap interval 0
description: updated
Changed in mir:
milestone: 0.9.0 → 0.10.0
Changed in mir:
assignee: nobody → Daniel van Vugt (vanvugt)
Changed in mir:
status: Triaged → In Progress
description: updated
summary: - Full screen (bypassed) surfaces are missing frames and appear to freeze
- with swap interval 0
+ Full screen (bypassed) surfaces (e.g. GLMark2Test) are missing frames
+ and appear to freeze or judder with swap interval 0
Changed in mir:
status: In Progress → Fix Committed
Changed in mir:
status: Fix Committed → Fix Released
Daniel van Vugt (vanvugt) wrote :

mir (0.10.0+15.04.20150107.2-0ubuntu1) vivid; urgency=medium

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

Other bug subscribers