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

Commit 68ad126

Browse files
author
Kaushik Iska
committed
revise docs and address CR comments
1 parent 2260067 commit 68ad126

File tree

8 files changed

+41
-85
lines changed

8 files changed

+41
-85
lines changed

ci/licenses_golden/licenses_flutter

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -576,6 +576,8 @@ FILE: ../../../flutter/shell/common/fixtures/shelltest_screenshot.png
576576
FILE: ../../../flutter/shell/common/input_events_unittests.cc
577577
FILE: ../../../flutter/shell/common/isolate_configuration.cc
578578
FILE: ../../../flutter/shell/common/isolate_configuration.h
579+
FILE: ../../../flutter/shell/common/layer_tree_holder.cc
580+
FILE: ../../../flutter/shell/common/layer_tree_holder.h
579581
FILE: ../../../flutter/shell/common/persistent_cache.cc
580582
FILE: ../../../flutter/shell/common/persistent_cache.h
581583
FILE: ../../../flutter/shell/common/persistent_cache_unittests.cc

flow/compositor_context.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,6 @@ enum class RasterStatus {
2727
// Frame needs to be resubmitted for rasterization. This is
2828
// currently only called when thread configuration change occurs.
2929
kResubmit,
30-
// Frame has been successfully rasterized, but "there are additional items in
31-
// the pipeline waiting to be consumed. This is currently
32-
// only called when thread configuration change occurs.
33-
kEnqueuePipeline,
3430
// Failed to rasterize the frame.
3531
kFailed
3632
};

shell/common/engine.h

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -406,25 +406,18 @@ class Engine final : public RuntimeDelegate, PointerDataDispatcher::Delegate {
406406
/// will cause the jank in the Flutter application:
407407
/// * The time taken by this method to create a layer-tree exceeds
408408
/// on frame interval (for example, 16.66 ms on a 60Hz display).
409-
/// * The time take by this method to generate a new layer-tree
410-
/// causes the current layer-tree pipeline depth to change. To
411-
/// illustrate this point, note that maximum pipeline depth used
412-
/// by layer tree in the engine is 2. If both the UI and GPU
413-
/// task runner tasks finish within one frame interval, the
414-
/// pipeline depth is one. If the UI thread happens to be
415-
/// working on a frame when the raster thread is still not done
416-
/// with the previous frame, the pipeline depth is 2. When the
417-
/// pipeline depth changes from 1 to 2, animations and UI
418-
/// interactions that cause the generation of the new layer tree
419-
/// appropriate for (frame_time + one frame interval) will
420-
/// actually end up at (frame_time + two frame intervals). This
421-
/// is not what code running on the UI thread expected would
422-
/// happen. This causes perceptible jank.
409+
/// * A new layer-tree produced by this method replaces a stale
410+
/// layer tree in `LayerTreeHolder`. See:
411+
/// `LayerTreeHolder::ReplaceIfNewer`. This could happen if
412+
/// rasterizer takes more than one frame interval to rasterize a
413+
/// layer tree. This would cause some frames to be skipped and
414+
/// could result in perceptible jank.
423415
///
424416
/// @param[in] frame_time The point at which the current frame interval
425417
/// began. May be used by animation interpolators,
426418
/// physics simulations, etc..
427419
///
420+
/// @see `LayerTreeHolder::ReplaceIfNewer`
428421
void BeginFrame(fml::TimePoint frame_time);
429422

430423
//----------------------------------------------------------------------------

shell/common/layer_tree_holder.cc

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,12 @@ std::unique_ptr<LayerTree> LayerTreeHolder::Get() {
1111
return std::move(layer_tree_);
1212
}
1313

14-
void LayerTreeHolder::ReplaceIfNewer(std::unique_ptr<LayerTree> layer_tree) {
14+
void LayerTreeHolder::ReplaceIfNewer(
15+
std::unique_ptr<LayerTree> proposed_layer_tree) {
1516
std::scoped_lock lock(layer_tree_mutex);
16-
if (IsEmpty()) {
17-
layer_tree_ = std::move(layer_tree);
18-
} else if (layer_tree_->target_time() < layer_tree->target_time()) {
19-
layer_tree_ = std::move(layer_tree);
17+
if (IsEmpty() ||
18+
layer_tree_->target_time() < proposed_layer_tree->target_time()) {
19+
layer_tree_ = std::move(proposed_layer_tree);
2020
}
2121
}
2222

shell/common/layer_tree_holder.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ class LayerTreeHolder {
2121

2222
std::unique_ptr<LayerTree> Get();
2323

24-
void ReplaceIfNewer(std::unique_ptr<LayerTree> layer_tree);
24+
void ReplaceIfNewer(std::unique_ptr<LayerTree> proposed_layer_tree);
2525

2626
private:
2727
mutable std::mutex layer_tree_mutex;

shell/common/rasterizer.cc

Lines changed: 9 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -121,29 +121,24 @@ void Rasterizer::Draw(std::shared_ptr<LayerTreeHolder> layer_tree_holder) {
121121
FML_DCHECK(task_runners_.GetRasterTaskRunner()->RunsTasksOnCurrentThread());
122122

123123
std::unique_ptr<LayerTree> layer_tree = layer_tree_holder->Get();
124-
RasterStatus raster_status = RasterStatus::kFailed;
125-
if (layer_tree) {
126-
raster_status = DoDraw(std::move(layer_tree));
127-
}
128-
129-
// if the raster status is to resubmit the frame, we push the frame to the
130-
// front of the queue and also change the consume status to more available.
131-
if (raster_status == RasterStatus::kResubmit) {
132-
layer_tree_holder->ReplaceIfNewer(std::move(resubmitted_layer_tree_));
133-
}
124+
RasterStatus raster_status =
125+
layer_tree ? DoDraw(std::move(layer_tree)) : RasterStatus::kFailed;
134126

135127
// Merging the thread as we know the next `Draw` should be run on the platform
136128
// thread.
137129
if (raster_status == RasterStatus::kResubmit) {
130+
layer_tree_holder->ReplaceIfNewer(std::move(resubmitted_layer_tree_));
138131
auto* external_view_embedder = surface_->GetExternalViewEmbedder();
139-
// We know only the `external_view_embedder` can
140-
// causes|RasterStatus::kResubmit|. Check to make sure.
141-
FML_DCHECK(external_view_embedder != nullptr);
132+
FML_DCHECK(external_view_embedder != nullptr)
133+
<< "kResubmit is an invalid raster status without external view "
134+
"embedder.";
142135
external_view_embedder->EndFrame(raster_thread_merger_);
143136
}
144137

145-
// Consume as many pipeline items as possible. But yield the event loop
138+
// Consume as many layer trees as possible. But yield the event loop
146139
// between successive tries.
140+
// Note: This behaviour is left as-is to be inline with the pipeline
141+
// semantics. TODO(kaushikiska): explore removing this block.
147142
if (!layer_tree_holder->IsEmpty()) {
148143
task_runners_.GetRasterTaskRunner()->PostTask(
149144
[weak_this = weak_factory_.GetWeakPtr(), layer_tree_holder]() {
@@ -299,29 +294,6 @@ RasterStatus Rasterizer::DoDraw(
299294
);
300295
}
301296

302-
// Pipeline pressure is applied from a couple of places:
303-
// rasterizer: When there are more items as of the time of Consume.
304-
// animator (via shell): Frame gets produces every vsync.
305-
// Enqueing here is to account for the following scenario:
306-
// T = 1
307-
// - one item (A) in the pipeline
308-
// - rasterizer starts (and merges the threads)
309-
// - pipeline consume result says no items to process
310-
// T = 2
311-
// - animator produces (B) to the pipeline
312-
// - applies pipeline pressure via platform thread.
313-
// T = 3
314-
// - rasterizes finished (and un-merges the threads)
315-
// - |Draw| for B yields as its on the wrong thread.
316-
// This enqueue ensures that we attempt to consume from the right
317-
// thread one more time after un-merge.
318-
if (raster_thread_merger_) {
319-
if (raster_thread_merger_->DecrementLease() ==
320-
fml::RasterThreadStatus::kUnmergedNow) {
321-
return RasterStatus::kEnqueuePipeline;
322-
}
323-
}
324-
325297
return raster_status;
326298
}
327299

shell/common/rasterizer.h

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -230,34 +230,26 @@ class Rasterizer final : public SnapshotDelegate {
230230
flutter::TextureRegistry* GetTextureRegistry();
231231

232232
//----------------------------------------------------------------------------
233-
/// @brief Takes the next item from the layer tree pipeline and executes
234-
/// the raster thread frame workload for that pipeline item to
235-
/// render a frame on the on-screen surface.
233+
/// @brief Takes the latest item from the layer tree holder and executes
234+
/// the raster thread frame workload for that item to render a
235+
/// frame on the on-screen surface.
236236
///
237-
/// Why does the draw call take a layer tree pipeline and not the
237+
/// Why does the draw call take a layer tree holder and not the
238238
/// layer tree directly?
239239
///
240-
/// The pipeline is the way book-keeping of frame workloads
241-
/// distributed across the multiple threads is managed. The
242-
/// rasterizer deals with the pipelines directly (instead of layer
243-
/// trees which is what it actually renders) because the pipeline
244-
/// consumer's workload must be accounted for within the pipeline
245-
/// itself. If the rasterizer took the layer tree directly, it
246-
/// would have to be taken out of the pipeline. That would signal
247-
/// the end of the frame workload and the pipeline would be ready
248-
/// for new frames. But the last frame has not been rendered by
249-
/// the frame yet! On the other hand, the pipeline must own the
250-
/// layer tree it renders because it keeps a reference to the last
251-
/// layer tree around till a new frame is rendered. So a simple
252-
/// reference wont work either. The `Rasterizer::DoDraw` method
253-
/// actually performs the GPU operations within the layer tree
254-
/// pipeline.
240+
/// The layer tree holder is a thread safe way to produce frame
241+
/// workloads from the UI thread and raster them on the raster
242+
/// thread. To account for scenarious where the UI thread
243+
/// continues to produce the frames while a raster task is queued,
244+
/// `Rasterizer::DoDraw` that gets executed on the raster thread,
245+
/// must pick up the newest layer tree produced by the UI thread.
246+
/// If we were to pass the layer tree as opposed to the holder, it
247+
/// would result in stale frames being rendered.
255248
///
256249
/// @see `Rasterizer::DoDraw`
257250
///
258-
/// @param[in] pipeline The layer tree pipeline to take the next layer tree
259-
/// to render from.
260-
/// TODO(kaushikiska) fix docs whereever pipeline is mentioned.
251+
/// @param[in] layer_tree_holder The layer tree holder to take the latest
252+
/// layer tree to render from.
261253
void Draw(std::shared_ptr<LayerTreeHolder> layer_tree_holder);
262254

263255
//----------------------------------------------------------------------------
@@ -425,7 +417,8 @@ class Rasterizer final : public SnapshotDelegate {
425417
std::unique_ptr<flutter::LayerTree> last_layer_tree_;
426418
// Set when we need attempt to rasterize the layer tree again. This layer_tree
427419
// has not successfully rasterized. This can happen due to the change in the
428-
// thread configuration. This will be inserted to the front of the pipeline.
420+
// thread configuration. This layer tree could be rasterized again if there
421+
// are no newer ones.
429422
std::unique_ptr<flutter::LayerTree> resubmitted_layer_tree_;
430423
fml::closure next_frame_callback_;
431424
bool user_override_resource_cache_bytes_;

shell/common/shell_test.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ void ShellTest::PumpOneFrame(Shell* shell,
136136
flutter::ViewportMetrics viewport_metrics,
137137
LayerTreeBuilder builder) {
138138
// Set viewport to nonempty, and call Animator::BeginFrame to make the layer
139-
// tree pipeline nonempty. Without either of this, the layer tree below
139+
// tree holder nonempty. Without either of this, the layer tree below
140140
// won't be rasterized.
141141
fml::AutoResetWaitableEvent latch;
142142
shell->GetTaskRunners().GetUITaskRunner()->PostTask(

0 commit comments

Comments
 (0)