Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 084da3d

Browse files
committed
add vsync_waiter comments
1 parent 51f2dc7 commit 084da3d

File tree

2 files changed

+54
-35
lines changed

2 files changed

+54
-35
lines changed

shell/platform/fuchsia/flutter/vsync_waiter.cc

Lines changed: 46 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -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.
79104
FrameTargetTimes 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.
194209
void 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.
200217
void 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.
227246
void 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.
235256
FrameTargetTimes VsyncWaiter::GetTargetTimesHelper(bool secondary_callback) {
236257
fml::TimeDelta presentation_interval =
237258
VsyncRecorder::GetInstance().GetCurrentVsyncInfo().presentation_interval;

shell/platform/fuchsia/flutter/vsync_waiter.h

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,13 @@ class VsyncWaiter final : public flutter::VsyncWaiter {
4444
~VsyncWaiter() override;
4545

4646
private:
47-
void RequestAFrameToBeScheduled();
47+
// |flutter::VsyncWaiter|
48+
void AwaitVSync() override;
49+
50+
// |flutter::VsyncWaiter|
51+
void AwaitVSyncForSecondaryCallback() override;
52+
53+
void FireCallbackMaybe();
4854
void OnVsync();
4955

5056
FrameTargetTimes GetTargetTimesHelper(bool secondary_callback);
@@ -61,20 +67,12 @@ class VsyncWaiter final : public flutter::VsyncWaiter {
6167
// and that Flutter is not producing multiple frames in a small interval.
6268
fml::TimePoint last_targetted_vsync_;
6369

64-
// This is true iff AwaitVsync() was called but we could not schedule a frame.
70+
// This is true iff AwaitVSync() was called but we could not schedule a frame.
6571
bool frame_request_pending_ = false;
6672

67-
// For accessing the VsyncWaiter via the UI thread, necessary for the callback
68-
// for AwaitVSync()
6973
std::unique_ptr<fml::WeakPtrFactory<VsyncWaiter>> weak_factory_ui_;
7074
fml::WeakPtrFactory<VsyncWaiter> weak_factory_;
7175

72-
// |flutter::VsyncWaiter|
73-
void AwaitVSync() override;
74-
75-
// |flutter::VsyncWaiter|
76-
void AwaitVSyncForSecondaryCallback() override;
77-
7876
FML_DISALLOW_COPY_AND_ASSIGN(VsyncWaiter);
7977
};
8078

0 commit comments

Comments
 (0)