@@ -76,6 +76,31 @@ fml::TimePoint VsyncWaiter::SnapToNextPhase(
7676 }
7777}
7878
79+ // This function takes in all relevant information to determining when should
80+ // the next frame be scheduled. It returns a pair of (frame_start_time,
81+ // frame_end_time) to be passed into FireCallback().
82+ //
83+ // Importantly, there are two invariants for correct and performant scheduling
84+ // that this function upholds:
85+ // 1. Schedule the next frame at least half a vsync interval from the previous
86+ // one. In practice, this means that every vsync interval Flutter produces
87+ // exactly one frame in steady state behavior.
88+ // 2. Only produce frames beginning in the future.
89+ //
90+ // |vsync_offset| - the time from the next vsync that the animator should begin
91+ // working on the next frame. For instance if vsyncs are at 0ms, 16ms, and 33ms,
92+ // and the |vsync_offset| is 5ms, then frames should begin at 11ms and 28ms.
93+ //
94+ // |vsync_interval| - the interval between vsyncs. Would be 16.6ms for a 60Hz
95+ // display.
96+ //
97+ // |last_targetted_vsync| - the last vsync targetted, which is usually the
98+ // frame_end_time returned from the last invocation of this function
99+ //
100+ // |now| - the current time
101+ //
102+ // |next_vsync| - the next vsync after |now|. This can be generated using the
103+ // SnapToNextPhase function.
79104FrameTargetTimes VsyncWaiter::GetTargetTimes (
80105 fml::TimeDelta vsync_offset,
81106 fml::TimeDelta vsync_interval,
@@ -94,7 +119,6 @@ FrameTargetTimes VsyncWaiter::GetTargetTimes(
94119
95120 // Start the frame after Scenic has finished its CPU work. This is
96121 // accomplished using the vsync_offset.
97- // fml::TimePoint frame_start_time = next_vsync - vsync_offset;
98122 fml::TimeDelta vsync_offset2 = vsync_interval - vsync_offset;
99123 fml::TimePoint frame_start_time =
100124 (next_vsync - vsync_interval) + vsync_offset2;
@@ -103,11 +127,7 @@ FrameTargetTimes VsyncWaiter::GetTargetTimes(
103127
104128 std::pair<fml::TimePoint, fml::TimePoint> pair;
105129
106- // Advance to next available slot. There are only two invariants:
107- // 1. Schedule the next frame at least half a vsync interval from the previous
108- // one. In practice, this means that every vsync interval Flutter produces
109- // exactly one frame in steady state behavior.
110- // 2. Only produce frames beginning in the future.
130+ // Advance to next available slot, keeping in mind the two invariants.
111131 while (frame_end_time < (last_targetted_vsync + (vsync_interval / 2 )) ||
112132 frame_start_time < now) {
113133 frame_start_time = frame_start_time + vsync_interval;
@@ -117,14 +137,15 @@ FrameTargetTimes VsyncWaiter::GetTargetTimes(
117137 pair.first = frame_start_time;
118138 pair.second = frame_end_time;
119139
140+ // Useful knowledge for analyzing traces.
120141 fml::TimePoint previous_vsync = next_vsync - vsync_interval;
121142 TRACE_DURATION (
122- " flutter" , " VsyncWaiter::GetTargetTimes" , " previous_vsync" ,
123- previous_vsync.ToEpochDelta ().ToMilliseconds (), " last_targetted" ,
124- last_targetted_vsync.ToEpochDelta ().ToMilliseconds (), " now" ,
125- fml::TimePoint::Now ().ToEpochDelta ().ToMilliseconds (), " next_vsync" ,
126- next_vsync.ToEpochDelta ().ToMilliseconds (), " frame_start_time" ,
127- frame_start_time.ToEpochDelta ().ToMilliseconds (), " frame_end_time" ,
143+ " flutter" , " VsyncWaiter::GetTargetTimes" , " previous_vsync(ms) " ,
144+ previous_vsync.ToEpochDelta ().ToMilliseconds (), " last_targetted(ms) " ,
145+ last_targetted_vsync.ToEpochDelta ().ToMilliseconds (), " now(ms) " ,
146+ fml::TimePoint::Now ().ToEpochDelta ().ToMilliseconds (), " next_vsync(ms)) " ,
147+ next_vsync.ToEpochDelta ().ToMilliseconds (), " frame_start_time(ms) " ,
148+ frame_start_time.ToEpochDelta ().ToMilliseconds (), " frame_end_time(ms) " ,
128149 frame_end_time.ToEpochDelta ().ToMilliseconds ());
129150
130151 return pair;
@@ -184,19 +205,15 @@ VsyncWaiter::~VsyncWaiter() {
184205 ui_latch.Wait ();
185206}
186207
187- // When the Animator wants to produce the next frame, it calls AwaitVsync() in
188- // order for it to know when the best time to do that is.
189- //
190- // There are two cases: either we are able to do immedatitely, or we have
191- // produced too many frames in a recent interval and need to wait for the
192- // underlying system, namely Scenic, to signal that the previous enqueued work
193- // has been processed and we can produce more work.
208+ // This function is called when the Animator wishes to schedule a new frame.
194209void VsyncWaiter::AwaitVSync () {
195210 TRACE_DURATION (" flutter" , " VsyncWaiter::AwaitVsync()" ,
196211 " request_already_pending" , frame_request_pending_);
197- RequestAFrameToBeScheduled ();
212+ FireCallbackMaybe ();
198213}
199214
215+ // This function is called when the Animator wants to know about the next vsync,
216+ // but not for frame scheduling purposes.
200217void VsyncWaiter::AwaitVSyncForSecondaryCallback () {
201218 TRACE_DURATION (" flutter" , " VsyncWaiter::AwaitVsyncForSecondaryCallback()" ,
202219 " request_already_pending" , frame_request_pending_);
@@ -206,9 +223,9 @@ void VsyncWaiter::AwaitVSyncForSecondaryCallback() {
206223}
207224
208225// Postcondition: Either a frame is scheduled or frame_request_pending_ is set
209- // to true.
210- void VsyncWaiter::RequestAFrameToBeScheduled () {
211- TRACE_DURATION (" flutter" , " RequestAFrameToBeScheduled " );
226+ // to true, meaning we will attempt to schedule a frame on the next |OnVsync| .
227+ void VsyncWaiter::FireCallbackMaybe () {
228+ TRACE_DURATION (" flutter" , " FireCallbackMaybe " );
212229
213230 if (session_connection_->CanRequestNewFrames ()) {
214231 FrameTargetTimes times = GetTargetTimesHelper (/* secondary_callback=*/ false );
@@ -223,15 +240,19 @@ void VsyncWaiter::RequestAFrameToBeScheduled() {
223240}
224241
225242// This function is called when the SessionConnection signals us to let us know
226- // that one or more frames Flutter has produced have been displayed.
243+ // that one or more frames Flutter has produced have been displayed. Note that
244+ // in practice this will be called several milliseconds after vsync, due to
245+ // CPU contention.
227246void VsyncWaiter::OnVsync () {
228247 TRACE_DURATION (" flutter" , " VsyncWaiter::OnVsync" );
229248
230249 if (frame_request_pending_) {
231- RequestAFrameToBeScheduled ();
250+ FireCallbackMaybe ();
232251 }
233252}
234253
254+ // A helper function for GetTargetTimes(), since many of the fields it takes
255+ // have to be derived from other state.
235256FrameTargetTimes VsyncWaiter::GetTargetTimesHelper (bool secondary_callback) {
236257 fml::TimeDelta presentation_interval =
237258 VsyncRecorder::GetInstance ().GetCurrentVsyncInfo ().presentation_interval ;
0 commit comments