Mir

Merge lp:~vanvugt/mir/fix-1665802 into lp:mir

Proposed by Daniel van Vugt
Status: Rejected
Rejected by: Daniel van Vugt
Proposed branch: lp:~vanvugt/mir/fix-1665802
Merge into: lp:mir
Diff against target: 163 lines (+105/-5)
3 files modified
src/client/frame_clock.cpp (+10/-1)
src/client/frame_clock.h (+1/-0)
tests/unit-tests/client/test_frame_clock.cpp (+94/-4)
To merge this branch: bzr merge lp:~vanvugt/mir/fix-1665802
Reviewer Review Type Date Requested Status
Daniel van Vugt Disapprove
Review via email: mp+318565@code.launchpad.net

Commit message

Proof of concept fix. This might be enough, or maybe not.

To post a comment you must log in.
Revision history for this message
Daniel van Vugt (vanvugt) wrote :

I'm hesitant to endorse this still, because it reduces our ability to catch up in almost-full-framerate scenarios across the board (instead opting to sleep and hope that's enough to give the server more GPU time). I feel this is something we shouldn't be "fixing" because it's not a Mir bug and more important devices (like everything other than Freedreno) could suffer slightly if we land this.

I'll look at other workarounds still that don't make the same sacrifice (although may be much less clean in code than this).

review: Disapprove

Unmerged revisions

4068. By Daniel van Vugt

Tidy up the test

4067. By Daniel van Vugt

Correct and clean up the fix. Tests all pass

4066. By Daniel van Vugt

Expand the test more to fail due to the latching

4065. By Daniel van Vugt

Enable the fix (and debug output). Tests pass but the flag is latching.
Needs a better test

4064. By Daniel van Vugt

Disable the fix and rewrite the regression test

4063. By Daniel van Vugt

Merge latest trunk

4062. By Daniel van Vugt

Expand the test and leave in debug output

4061. By Daniel van Vugt

Fix the fix. Now all tests pass.

4060. By Daniel van Vugt

Try to fix the bug, and bad expectations in older tests

4059. By Daniel van Vugt

Write a detailed regression test (presently failing)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/client/frame_clock.cpp'
--- src/client/frame_clock.cpp 2016-11-29 08:00:45 +0000
+++ src/client/frame_clock.cpp 2017-03-01 04:44:28 +0000
@@ -103,7 +103,7 @@
103 * Crucially this is not required on most frames, so that even if it is103 * Crucially this is not required on most frames, so that even if it is
104 * implemented as a round trip to the server, that won't happen often.104 * implemented as a round trip to the server, that won't happen often.
105 */105 */
106 if (missed_frames > 1 || config_changed)106 if (missed_frames > 1 || config_changed || !throttled)
107 {107 {
108 lock.unlock();108 lock.unlock();
109 auto const server_frame = resync_callback();109 auto const server_frame = resync_callback();
@@ -152,5 +152,14 @@
152 target = target + missed_frames * period;152 target = target + missed_frames * period;
153 }153 }
154154
155 /*
156 * Often we'll be targeting the past in order to catch up after a previous
157 * slow frame. That's correct, but try to not do it multiple frames in a
158 * row, since that might saturate a low-power GPU, which might then starve
159 * the server of GPU time if the driver lacks adequate fair scheduling
160 * (e.g. Freedreno/Gallium LP: #1665802)
161 */
162 throttled = target > now;
163
155 return target;164 return target;
156}165}
157166
=== modified file 'src/client/frame_clock.h'
--- src/client/frame_clock.h 2016-12-15 08:15:54 +0000
+++ src/client/frame_clock.h 2017-03-01 04:44:28 +0000
@@ -66,6 +66,7 @@
66 mutable bool config_changed;66 mutable bool config_changed;
67 std::chrono::nanoseconds period;67 std::chrono::nanoseconds period;
68 ResyncCallback resync_callback;68 ResyncCallback resync_callback;
69 mutable bool throttled = true;
69};70};
7071
71}} // namespace mir::client72}} // namespace mir::client
7273
=== modified file 'tests/unit-tests/client/test_frame_clock.cpp'
--- tests/unit-tests/client/test_frame_clock.cpp 2017-02-28 13:25:18 +0000
+++ tests/unit-tests/client/test_frame_clock.cpp 2017-03-01 04:44:28 +0000
@@ -135,9 +135,9 @@
135 fake_sleep_for(one_frame * 7 / 6); // long render time; over a frame135 fake_sleep_for(one_frame * 7 / 6); // long render time; over a frame
136136
137 auto d = clock.next_frame_after(c);137 auto d = clock.next_frame_after(c);
138 EXPECT_EQ(one_frame, d - c);138 EXPECT_EQ(2*one_frame, d - c);
139139
140 EXPECT_LT(d, now);140 EXPECT_GT(d, now);
141141
142 fake_sleep_until(d);142 fake_sleep_until(d);
143 fake_sleep_for(one_frame/4); // short render time143 fake_sleep_for(one_frame/4); // short render time
@@ -392,8 +392,9 @@
392 fake_sleep_for(one_frame * 8 / 5); // Render time: 1.6 frames392 fake_sleep_for(one_frame * 8 / 5); // Render time: 1.6 frames
393393
394 auto d = clock.next_frame_after(c);394 auto d = clock.next_frame_after(c);
395 EXPECT_EQ(2*one_frame, d - c); // One frame skipped395 EXPECT_EQ(3*one_frame, d - c); // Two frames skipped (since c targeted
396 EXPECT_LT(d, now); // Targets the past, catching up again396 // the past but d the future)
397 EXPECT_GT(d, now); // Targets the future
397398
398 fake_sleep_until(d);399 fake_sleep_until(d);
399 fake_sleep_for(one_frame/4); // Short render time, immediate recovery400 fake_sleep_for(one_frame/4); // Short render time, immediate recovery
@@ -403,6 +404,95 @@
403 EXPECT_GT(e, now); // And targeting the future404 EXPECT_GT(e, now); // And targeting the future
404}405}
405406
407TEST_F(FrameClockTest, does_not_continuously_target_the_past)
408{ // Regression test for LP: #1665802
409 FrameClock clock(with_fake_time);
410 auto& now = fake_time[CLOCK_MONOTONIC];
411 clock.set_period(one_frame);
412
413 auto a = clock.next_frame_after(PosixTimestamp());
414 fake_sleep_until(a);
415 fake_sleep_for(one_frame / 9); // Start with a fast frame
416
417 auto b = clock.next_frame_after(a);
418 ASSERT_GT(b, now);
419
420 fake_sleep_until(b);
421 fake_sleep_for(one_frame * 3 / 2); // Render time: 1.5 frames
422
423 auto c = clock.next_frame_after(b);
424 ASSERT_LT(c, now); // Targets the past, catching up
425 ASSERT_EQ(one_frame, c - b); // No frame skipped
426
427 fake_sleep_until(c);
428
429 bool targeted_past = false;
430
431 auto d = c;
432 for (int slow_frame = 0; slow_frame < 10; ++slow_frame)
433 {
434 fake_sleep_for(one_frame * 8 / 5); // Render time: 1.6 frames
435 d = clock.next_frame_after(c);
436
437 bool targets_past = d < now;
438 if (targeted_past)
439 ASSERT_FALSE(targets_past);
440 targeted_past = targets_past;
441
442 // May target the future, but not too far in the future:
443 ASSERT_LE(d, now+one_frame);
444 c = d;
445 fake_sleep_until(d);
446 }
447
448 fake_sleep_for(one_frame/4); // Short render time, immediate recovery
449
450 auto e = clock.next_frame_after(d);
451 ASSERT_EQ(one_frame, e - d); // No frame skipped. We have recovered.
452 ASSERT_GT(e, now); // And targeting the future
453 targeted_past = false;
454
455 /*
456 * In the original bug LP: #1665802 it appeared that the GPU could only
457 * sustain quarter frame rate. So test that scenario too...
458 */
459 auto f = e;
460 for (int slower_frame = 0; slower_frame < 10; ++slower_frame)
461 {
462 fake_sleep_for(one_frame * 17 / 5); // Render time: 3.4 frames
463 f = clock.next_frame_after(e);
464
465 bool targets_past = f < now;
466 if (targeted_past)
467 ASSERT_FALSE(targets_past);
468 targeted_past = targets_past;
469
470 // May target the future, but not too far in the future:
471 ASSERT_LE(f, now+one_frame); // But not too far in the future
472 e = f;
473 fake_sleep_until(f);
474 }
475
476 auto g = f;
477
478 for (int recovered_frame = 0; recovered_frame < 10; ++recovered_frame)
479 {
480 fake_sleep_for(one_frame / 10);
481 g = clock.next_frame_after(f);
482 ASSERT_GT(g, now);
483 ASSERT_LE(g, now+one_frame);
484 ASSERT_EQ(one_frame, g - f);
485 f = g;
486 fake_sleep_until(g);
487 }
488
489 fake_sleep_for(one_frame * 3 / 2); // Render time: 1.5 frames
490
491 auto h = clock.next_frame_after(g);
492 ASSERT_LT(h, now); // Targets the past, catching up
493 ASSERT_EQ(one_frame, h - g); // No frame skipped
494}
495
406TEST_F(FrameClockTest, nesting_adds_zero_lag)496TEST_F(FrameClockTest, nesting_adds_zero_lag)
407{497{
408 FrameClock inner(with_fake_time);498 FrameClock inner(with_fake_time);

Subscribers

People subscribed via source and target branches