From e084a92efd265b49aad01a76d4cdb5cfe42abbe7 Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Tue, 15 Aug 2023 13:08:31 -0700 Subject: [PATCH 01/48] Split FrameStatus of CompositorContext --- flow/compositor_context.cc | 8 ++++---- flow/compositor_context.h | 29 ++++++++++++++++++++++++++--- shell/common/rasterizer.cc | 15 +++++++++------ shell/common/rasterizer.h | 2 ++ 4 files changed, 41 insertions(+), 13 deletions(-) diff --git a/flow/compositor_context.cc b/flow/compositor_context.cc index 2c7593c1625e8..ec9788a23b70c 100644 --- a/flow/compositor_context.cc +++ b/flow/compositor_context.cc @@ -114,7 +114,7 @@ CompositorContext::ScopedFrame::~ScopedFrame() { context_.EndFrame(*this, instrumentation_enabled_); } -RasterStatus CompositorContext::ScopedFrame::Raster( +CompositorContext::FrameStatus CompositorContext::ScopedFrame::Raster( flutter::LayerTree& layer_tree, bool ignore_raster_cache, FrameDamage* frame_damage) { @@ -142,10 +142,10 @@ RasterStatus CompositorContext::ScopedFrame::Raster( } if (post_preroll_result == PostPrerollResult::kResubmitFrame) { - return RasterStatus::kResubmit; + return FrameStatus::kResubmit; } if (post_preroll_result == PostPrerollResult::kSkipAndRetryFrame) { - return RasterStatus::kSkipAndRetry; + return FrameStatus::kSkipAndRetry; } if (aiks_context_) { @@ -154,7 +154,7 @@ RasterStatus CompositorContext::ScopedFrame::Raster( PaintLayerTreeSkia(layer_tree, clip_rect, needs_save_layer, ignore_raster_cache); } - return RasterStatus::kSuccess; + return FrameStatus::kSuccess; } void CompositorContext::ScopedFrame::PaintLayerTreeSkia( diff --git a/flow/compositor_context.h b/flow/compositor_context.h index 30aae4736c928..eb8a6b2306efc 100644 --- a/flow/compositor_context.h +++ b/flow/compositor_context.h @@ -114,6 +114,29 @@ class FrameDamage { class CompositorContext { public: + enum FrameStatus { + // Frame has been successfully rasterized. + kSuccess, + // Frame should be submitted twice. This is only used on Android when + // switching the background surface to FlutterImageView. + // + // On Android, the first frame doesn't make the image available + // to the ImageReader right away. The second frame does. + // + // TODO(egarciad): https://github.com/flutter/flutter/issues/65652 + kResubmit, + // Frame is dropped and a new frame with the same layer tree should be + // attempted. + // + // This is currently used to wait for the thread merger to merge + // the raster and platform threads. + // + // Since the thread merger may be disabled, + // TODO(dkwingsmt): The original doc ended like this. I have no idea what + // the original author wanted to say. + kSkipAndRetry, + }; + class ScopedFrame { public: ScopedFrame(CompositorContext& context, @@ -144,9 +167,9 @@ class CompositorContext { impeller::AiksContext* aiks_context() const { return aiks_context_; } - virtual RasterStatus Raster(LayerTree& layer_tree, - bool ignore_raster_cache, - FrameDamage* frame_damage); + virtual FrameStatus Raster(LayerTree& layer_tree, + bool ignore_raster_cache, + FrameDamage* frame_damage); private: void PaintLayerTreeSkia(flutter::LayerTree& layer_tree, diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index d7d1338c1a533..734d56fc93def 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -597,14 +597,13 @@ RasterStatus Rasterizer::DrawToSurfaceUnsafe( ignore_raster_cache = false; } - RasterStatus raster_status = + FrameStatus frame_status = compositor_frame->Raster(layer_tree, // layer tree ignore_raster_cache, // ignore raster cache damage.get() // frame damage ); - if (raster_status == RasterStatus::kFailed || - raster_status == RasterStatus::kSkipAndRetry) { - return raster_status; + if (frame_status == FrameStatus::kSkipAndRetry) { + return RasterStatus::kSkipAndRetry; } SurfaceFrame::SubmitInfo submit_info; @@ -634,7 +633,7 @@ RasterStatus Rasterizer::DrawToSurfaceUnsafe( // Do not update raster cache metrics for kResubmit because that status // indicates that the frame was not actually painted. - if (raster_status != RasterStatus::kResubmit) { + if (frame_status != FrameStatus::kResubmit) { compositor_context_->raster_cache().EndFrame(); } @@ -646,7 +645,11 @@ RasterStatus Rasterizer::DrawToSurfaceUnsafe( surface_->GetContext()->performDeferredCleanup(kSkiaCleanupExpiration); } - return raster_status; + if (frame_status == FrameStatus::kResubmit) { + return RasterStatus::kResubmit; + } else { + return RasterStatus::kSuccess; + } } return RasterStatus::kFailed; diff --git a/shell/common/rasterizer.h b/shell/common/rasterizer.h index b17242342c084..bff2293b92295 100644 --- a/shell/common/rasterizer.h +++ b/shell/common/rasterizer.h @@ -500,6 +500,8 @@ class Rasterizer final : public SnapshotDelegate, void DisableThreadMergerIfNeeded(); private: + using FrameStatus = CompositorContext::FrameStatus; + // |SnapshotDelegate| std::unique_ptr MakeSkiaGpuImage( sk_sp display_list, From f25f09a321a643233a6d99d537e7f140123f79c4 Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Tue, 15 Aug 2023 13:32:58 -0700 Subject: [PATCH 02/48] Extract DrawSurfaceStatus --- shell/common/rasterizer.cc | 61 ++++++++++++++++++++++++-------------- shell/common/rasterizer.h | 41 +++++++++++++++++++++---- 2 files changed, 74 insertions(+), 28 deletions(-) diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index 734d56fc93def..ba17728997cd6 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -173,12 +173,12 @@ void Rasterizer::DrawLastLayerTree( if (!last_layer_tree_ || !surface_) { return; } - RasterStatus raster_status = DrawToSurface( + DrawSurfaceStatus draw_surface_status = DrawToSurface( *frame_timings_recorder, *last_layer_tree_, last_device_pixel_ratio_); // EndFrame should perform cleanups for the external_view_embedder. if (external_view_embedder_ && external_view_embedder_->GetUsedThisFrame()) { - bool should_resubmit_frame = ShouldResubmitFrame(raster_status); + bool should_resubmit_frame = ShouldResubmitSurface(draw_surface_status); external_view_embedder_->SetUsedThisFrame(false); external_view_embedder_->EndFrame(should_resubmit_frame, raster_thread_merger_); @@ -268,6 +268,12 @@ bool Rasterizer::ShouldResubmitFrame(const RasterStatus& raster_status) { raster_status == RasterStatus::kSkipAndRetry; } +bool Rasterizer::ShouldResubmitSurface( + const DrawSurfaceStatus& draw_surface_status) { + return draw_surface_status == DrawSurfaceStatus::kResubmit || + draw_surface_status == DrawSurfaceStatus::kSkipAndRetry; +} + namespace { std::unique_ptr MakeBitmapImage( const sk_sp& display_list, @@ -399,20 +405,26 @@ RasterStatus Rasterizer::DoDraw( PersistentCache* persistent_cache = PersistentCache::GetCacheForProcess(); persistent_cache->ResetStoredNewShaders(); - RasterStatus raster_status = + DrawSurfaceStatus draw_surface_status = DrawToSurface(*frame_timings_recorder, *layer_tree, device_pixel_ratio); - if (raster_status == RasterStatus::kSuccess) { + if (draw_surface_status == DrawSurfaceStatus::kSuccess) { last_layer_tree_ = std::move(layer_tree); last_device_pixel_ratio_ = device_pixel_ratio; - } else if (ShouldResubmitFrame(raster_status)) { + } else if (ShouldResubmitSurface(draw_surface_status)) { resubmitted_pixel_ratio_ = device_pixel_ratio; resubmitted_layer_tree_ = std::move(layer_tree); resubmitted_recorder_ = frame_timings_recorder->CloneUntil( FrameTimingsRecorder::State::kBuildEnd); - return raster_status; - } else if (raster_status == RasterStatus::kDiscarded) { - return raster_status; + if (draw_surface_status == DrawSurfaceStatus::kResubmit) { + return RasterStatus::kResubmit; + } else { + return RasterStatus::kSkipAndRetry; + } + } else if (draw_surface_status == DrawSurfaceStatus::kDiscarded) { + return RasterStatus::kDiscarded; } + FML_DCHECK(draw_surface_status == DrawSurfaceStatus::kSuccess || + draw_surface_status == DrawSurfaceStatus::kFailed); if (persistent_cache->IsDumpingSkp() && persistent_cache->StoredNewShaders()) { @@ -483,37 +495,42 @@ RasterStatus Rasterizer::DoDraw( } } - return raster_status; + if (draw_surface_status == DrawSurfaceStatus::kSuccess) { + return RasterStatus::kSuccess; + } else { + return RasterStatus::kFailed; + } } -RasterStatus Rasterizer::DrawToSurface( +Rasterizer::DrawSurfaceStatus Rasterizer::DrawToSurface( FrameTimingsRecorder& frame_timings_recorder, flutter::LayerTree& layer_tree, float device_pixel_ratio) { TRACE_EVENT0("flutter", "Rasterizer::DrawToSurface"); FML_DCHECK(surface_); - RasterStatus raster_status; + DrawSurfaceStatus draw_surface_status; if (surface_->AllowsDrawingWhenGpuDisabled()) { - raster_status = DrawToSurfaceUnsafe(frame_timings_recorder, layer_tree, - device_pixel_ratio); + draw_surface_status = DrawToSurfaceUnsafe(frame_timings_recorder, + layer_tree, device_pixel_ratio); } else { delegate_.GetIsGpuDisabledSyncSwitch()->Execute( fml::SyncSwitch::Handlers() - .SetIfTrue([&] { raster_status = RasterStatus::kDiscarded; }) + .SetIfTrue( + [&] { draw_surface_status = DrawSurfaceStatus::kDiscarded; }) .SetIfFalse([&] { - raster_status = DrawToSurfaceUnsafe( + draw_surface_status = DrawToSurfaceUnsafe( frame_timings_recorder, layer_tree, device_pixel_ratio); })); } - return raster_status; + return draw_surface_status; } /// Unsafe because it assumes we have access to the GPU which isn't the case /// when iOS is backgrounded, for example. /// \see Rasterizer::DrawToSurface -RasterStatus Rasterizer::DrawToSurfaceUnsafe( +Rasterizer::DrawSurfaceStatus Rasterizer::DrawToSurfaceUnsafe( FrameTimingsRecorder& frame_timings_recorder, flutter::LayerTree& layer_tree, float device_pixel_ratio) { @@ -542,7 +559,7 @@ RasterStatus Rasterizer::DrawToSurfaceUnsafe( if (frame == nullptr) { frame_timings_recorder.RecordRasterEnd( &compositor_context_->raster_cache()); - return RasterStatus::kFailed; + return DrawSurfaceStatus::kFailed; } // If the external view embedder has specified an optional root surface, the @@ -603,7 +620,7 @@ RasterStatus Rasterizer::DrawToSurfaceUnsafe( damage.get() // frame damage ); if (frame_status == FrameStatus::kSkipAndRetry) { - return RasterStatus::kSkipAndRetry; + return DrawSurfaceStatus::kSkipAndRetry; } SurfaceFrame::SubmitInfo submit_info; @@ -646,13 +663,13 @@ RasterStatus Rasterizer::DrawToSurfaceUnsafe( } if (frame_status == FrameStatus::kResubmit) { - return RasterStatus::kResubmit; + return DrawSurfaceStatus::kResubmit; } else { - return RasterStatus::kSuccess; + return DrawSurfaceStatus::kSuccess; } } - return RasterStatus::kFailed; + return DrawSurfaceStatus::kFailed; } static sk_sp ScreenshotLayerTreeAsPicture( diff --git a/shell/common/rasterizer.h b/shell/common/rasterizer.h index bff2293b92295..c691499996672 100644 --- a/shell/common/rasterizer.h +++ b/shell/common/rasterizer.h @@ -502,6 +502,32 @@ class Rasterizer final : public SnapshotDelegate, private: using FrameStatus = CompositorContext::FrameStatus; + enum DrawSurfaceStatus { + // Frame has been successfully rasterized. + kSuccess, + // Frame is submitted twice. This is only used on Android when + // switching the background surface to FlutterImageView. + // + // On Android, the first frame doesn't make the image available + // to the ImageReader right away. The second frame does. + // + // TODO(egarciad): https://github.com/flutter/flutter/issues/65652 + kResubmit, + // Frame is dropped and a new frame with the same layer tree is + // attempted. + // + // This is currently used to wait for the thread merger to merge + // the raster and platform threads. + // + // Since the thread merger may be disabled, + kSkipAndRetry, + // Failed to rasterize the frame. + kFailed, + // Layer tree was discarded due to LayerTreeDiscardCallback or inability to + // access the GPU. + kDiscarded, + }; + // |SnapshotDelegate| std::unique_ptr MakeSkiaGpuImage( sk_sp display_list, @@ -561,18 +587,21 @@ class Rasterizer final : public SnapshotDelegate, std::unique_ptr layer_tree, float device_pixel_ratio); - RasterStatus DrawToSurface(FrameTimingsRecorder& frame_timings_recorder, - flutter::LayerTree& layer_tree, - float device_pixel_ratio); + DrawSurfaceStatus DrawToSurface(FrameTimingsRecorder& frame_timings_recorder, + flutter::LayerTree& layer_tree, + float device_pixel_ratio); - RasterStatus DrawToSurfaceUnsafe(FrameTimingsRecorder& frame_timings_recorder, - flutter::LayerTree& layer_tree, - float device_pixel_ratio); + DrawSurfaceStatus DrawToSurfaceUnsafe( + FrameTimingsRecorder& frame_timings_recorder, + flutter::LayerTree& layer_tree, + float device_pixel_ratio); void FireNextFrameCallbackIfPresent(); static bool NoDiscard(const flutter::LayerTree& layer_tree) { return false; } static bool ShouldResubmitFrame(const RasterStatus& raster_status); + static bool ShouldResubmitSurface( + const DrawSurfaceStatus& draw_surface_status); Delegate& delegate_; MakeGpuImageBehavior gpu_image_behavior_; From 3977e16955182692f5c260f519f98ed81b5d71fb Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Tue, 15 Aug 2023 14:17:58 -0700 Subject: [PATCH 03/48] Simplify DrawStatus --- shell/common/rasterizer.cc | 18 ++++++++++++------ shell/common/rasterizer.h | 14 ++++++++++++-- shell/common/rasterizer_unittests.cc | 24 ++++++++++++------------ 3 files changed, 36 insertions(+), 20 deletions(-) diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index ba17728997cd6..2a483b0e00716 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -185,14 +185,13 @@ void Rasterizer::DrawLastLayerTree( } } -RasterStatus Rasterizer::Draw( - const std::shared_ptr& pipeline, - LayerTreeDiscardCallback discard_callback) { +DrawStatus Rasterizer::Draw(const std::shared_ptr& pipeline, + LayerTreeDiscardCallback discard_callback) { TRACE_EVENT0("flutter", "GPURasterizer::Draw"); if (raster_thread_merger_ && !raster_thread_merger_->IsOnRasterizingThread()) { // we yield and let this frame be serviced on the right thread. - return RasterStatus::kYielded; + return DrawStatus::kFailed; } FML_DCHECK(delegate_.GetTaskRunners() .GetRasterTaskRunner() @@ -215,7 +214,7 @@ RasterStatus Rasterizer::Draw( PipelineConsumeResult consume_result = pipeline->Consume(consumer); if (consume_result == PipelineConsumeResult::NoneAvailable) { - return RasterStatus::kFailed; + return DrawStatus::kFailed; } // if the raster status is to resubmit the frame, we push the frame to the // front of the queue and also change the consume status to more available. @@ -260,7 +259,14 @@ RasterStatus Rasterizer::Draw( break; } - return raster_status; + switch (raster_status) { + case RasterStatus::kDiscarded: + return DrawStatus::kDiscarded; + case RasterStatus::kFailed: + return DrawStatus::kFailed; + default: + return DrawStatus::kSuccess; + } } bool Rasterizer::ShouldResubmitFrame(const RasterStatus& raster_status) { diff --git a/shell/common/rasterizer.h b/shell/common/rasterizer.h index c691499996672..62709c34ee3e9 100644 --- a/shell/common/rasterizer.h +++ b/shell/common/rasterizer.h @@ -47,6 +47,16 @@ class AiksContext; namespace flutter { +enum class DrawStatus { + // Frame has been successfully rasterized. + kSuccess, + // Failed to rasterize the frame. + kFailed, + // Layer tree was discarded due to LayerTreeDiscardCallback or inability to + // access the GPU. + kDiscarded, +}; + //------------------------------------------------------------------------------ /// The rasterizer is a component owned by the shell that resides on the raster /// task runner. Each shell owns exactly one instance of a rasterizer. The @@ -273,8 +283,8 @@ class Rasterizer final : public SnapshotDelegate, /// @param[in] discard_callback if specified and returns true, the layer tree /// is discarded instead of being rendered /// - RasterStatus Draw(const std::shared_ptr& pipeline, - LayerTreeDiscardCallback discard_callback = NoDiscard); + DrawStatus Draw(const std::shared_ptr& pipeline, + LayerTreeDiscardCallback discard_callback = NoDiscard); //---------------------------------------------------------------------------- /// @brief The type of the screenshot to obtain of the previously diff --git a/shell/common/rasterizer_unittests.cc b/shell/common/rasterizer_unittests.cc index 5307dcacccfdf..c24a8c08abd7d 100644 --- a/shell/common/rasterizer_unittests.cc +++ b/shell/common/rasterizer_unittests.cc @@ -518,8 +518,8 @@ TEST(RasterizerTest, externalViewEmbedderDoesntEndFrameWhenNotUsedThisFrame) { EXPECT_TRUE(result.success); // Always discard the layer tree. auto discard_callback = [](LayerTree&) { return true; }; - RasterStatus status = rasterizer->Draw(pipeline, discard_callback); - EXPECT_EQ(status, RasterStatus::kDiscarded); + DrawStatus status = rasterizer->Draw(pipeline, discard_callback); + EXPECT_EQ(status, DrawStatus::kDiscarded); latch.Signal(); }); latch.Wait(); @@ -562,8 +562,8 @@ TEST(RasterizerTest, externalViewEmbedderDoesntEndFrameWhenPipelineIsEmpty) { thread_host.raster_thread->GetTaskRunner()->PostTask([&] { auto pipeline = std::make_shared(/*depth=*/10); auto no_discard = [](LayerTree&) { return false; }; - RasterStatus status = rasterizer->Draw(pipeline, no_discard); - EXPECT_EQ(status, RasterStatus::kFailed); + DrawStatus status = rasterizer->Draw(pipeline, no_discard); + EXPECT_EQ(status, DrawStatus::kFailed); latch.Signal(); }); latch.Wait(); @@ -678,8 +678,8 @@ TEST( pipeline->Produce().Complete(std::move(layer_tree_item)); EXPECT_TRUE(result.success); auto no_discard = [](LayerTree&) { return false; }; - RasterStatus status = rasterizer->Draw(pipeline, no_discard); - EXPECT_EQ(status, RasterStatus::kSuccess); + DrawStatus status = rasterizer->Draw(pipeline, no_discard); + EXPECT_EQ(status, DrawStatus::kSuccess); latch.Signal(); }); latch.Wait(); @@ -736,8 +736,8 @@ TEST( pipeline->Produce().Complete(std::move(layer_tree_item)); EXPECT_TRUE(result.success); auto no_discard = [](LayerTree&) { return false; }; - RasterStatus status = rasterizer->Draw(pipeline, no_discard); - EXPECT_EQ(status, RasterStatus::kSuccess); + DrawStatus status = rasterizer->Draw(pipeline, no_discard); + EXPECT_EQ(status, DrawStatus::kSuccess); latch.Signal(); }); latch.Wait(); @@ -793,8 +793,8 @@ TEST( pipeline->Produce().Complete(std::move(layer_tree_item)); EXPECT_TRUE(result.success); auto no_discard = [](LayerTree&) { return false; }; - RasterStatus status = rasterizer->Draw(pipeline, no_discard); - EXPECT_EQ(status, RasterStatus::kDiscarded); + DrawStatus status = rasterizer->Draw(pipeline, no_discard); + EXPECT_EQ(status, DrawStatus::kDiscarded); latch.Signal(); }); latch.Wait(); @@ -849,8 +849,8 @@ TEST( pipeline->Produce().Complete(std::move(layer_tree_item)); EXPECT_TRUE(result.success); auto no_discard = [](LayerTree&) { return false; }; - RasterStatus status = rasterizer->Draw(pipeline, no_discard); - EXPECT_EQ(status, RasterStatus::kFailed); + DrawStatus status = rasterizer->Draw(pipeline, no_discard); + EXPECT_EQ(status, DrawStatus::kFailed); latch.Signal(); }); latch.Wait(); From 0b9483de6409324d6a697571e33f8ac5d10998aa Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Tue, 15 Aug 2023 14:27:53 -0700 Subject: [PATCH 04/48] DoDrawStatus, and rename back to RasterStatus --- flow/compositor_context.cc | 8 +++---- flow/compositor_context.h | 47 ++++++-------------------------------- shell/common/rasterizer.cc | 40 ++++++++++++++++---------------- shell/common/rasterizer.h | 39 +++++++++++++++++++++++++++---- 4 files changed, 66 insertions(+), 68 deletions(-) diff --git a/flow/compositor_context.cc b/flow/compositor_context.cc index ec9788a23b70c..2c7593c1625e8 100644 --- a/flow/compositor_context.cc +++ b/flow/compositor_context.cc @@ -114,7 +114,7 @@ CompositorContext::ScopedFrame::~ScopedFrame() { context_.EndFrame(*this, instrumentation_enabled_); } -CompositorContext::FrameStatus CompositorContext::ScopedFrame::Raster( +RasterStatus CompositorContext::ScopedFrame::Raster( flutter::LayerTree& layer_tree, bool ignore_raster_cache, FrameDamage* frame_damage) { @@ -142,10 +142,10 @@ CompositorContext::FrameStatus CompositorContext::ScopedFrame::Raster( } if (post_preroll_result == PostPrerollResult::kResubmitFrame) { - return FrameStatus::kResubmit; + return RasterStatus::kResubmit; } if (post_preroll_result == PostPrerollResult::kSkipAndRetryFrame) { - return FrameStatus::kSkipAndRetry; + return RasterStatus::kSkipAndRetry; } if (aiks_context_) { @@ -154,7 +154,7 @@ CompositorContext::FrameStatus CompositorContext::ScopedFrame::Raster( PaintLayerTreeSkia(layer_tree, clip_rect, needs_save_layer, ignore_raster_cache); } - return FrameStatus::kSuccess; + return RasterStatus::kSuccess; } void CompositorContext::ScopedFrame::PaintLayerTreeSkia( diff --git a/flow/compositor_context.h b/flow/compositor_context.h index eb8a6b2306efc..309cbde87502d 100644 --- a/flow/compositor_context.h +++ b/flow/compositor_context.h @@ -26,7 +26,7 @@ class LayerTree; enum class RasterStatus { // Frame has been successfully rasterized. kSuccess, - // Frame is submitted twice. This is only used on Android when + // Frame should be submitted twice. This is only used on Android when // switching the background surface to FlutterImageView. // // On Android, the first frame doesn't make the image available @@ -34,26 +34,16 @@ enum class RasterStatus { // // TODO(egarciad): https://github.com/flutter/flutter/issues/65652 kResubmit, - // Frame is dropped and a new frame with the same layer tree is + // Frame is dropped and a new frame with the same layer tree should be // attempted. // // This is currently used to wait for the thread merger to merge // the raster and platform threads. // // Since the thread merger may be disabled, + // TODO(dkwingsmt): The original doc ended like this. I have no idea what + // the original author wanted to say. kSkipAndRetry, - // Frame has been successfully rasterized, but "there are additional items in - // the pipeline waiting to be consumed. This is currently - // only used when thread configuration change occurs. - kEnqueuePipeline, - // Failed to rasterize the frame. - kFailed, - // Layer tree was discarded due to LayerTreeDiscardCallback or inability to - // access the GPU. - kDiscarded, - // Drawing was yielded to allow the correct thread to draw as a result of the - // RasterThreadMerger. - kYielded, }; class FrameDamage { @@ -114,29 +104,6 @@ class FrameDamage { class CompositorContext { public: - enum FrameStatus { - // Frame has been successfully rasterized. - kSuccess, - // Frame should be submitted twice. This is only used on Android when - // switching the background surface to FlutterImageView. - // - // On Android, the first frame doesn't make the image available - // to the ImageReader right away. The second frame does. - // - // TODO(egarciad): https://github.com/flutter/flutter/issues/65652 - kResubmit, - // Frame is dropped and a new frame with the same layer tree should be - // attempted. - // - // This is currently used to wait for the thread merger to merge - // the raster and platform threads. - // - // Since the thread merger may be disabled, - // TODO(dkwingsmt): The original doc ended like this. I have no idea what - // the original author wanted to say. - kSkipAndRetry, - }; - class ScopedFrame { public: ScopedFrame(CompositorContext& context, @@ -167,9 +134,9 @@ class CompositorContext { impeller::AiksContext* aiks_context() const { return aiks_context_; } - virtual FrameStatus Raster(LayerTree& layer_tree, - bool ignore_raster_cache, - FrameDamage* frame_damage); + virtual RasterStatus Raster(LayerTree& layer_tree, + bool ignore_raster_cache, + FrameDamage* frame_damage); private: void PaintLayerTreeSkia(flutter::LayerTree& layer_tree, diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index 2a483b0e00716..ada57268df03a 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -197,7 +197,7 @@ DrawStatus Rasterizer::Draw(const std::shared_ptr& pipeline, .GetRasterTaskRunner() ->RunsTasksOnCurrentThread()); - RasterStatus raster_status = RasterStatus::kFailed; + DoDrawStatus raster_status = DoDrawStatus::kFailed; LayerTreePipeline::Consumer consumer = [&](std::unique_ptr item) { std::unique_ptr layer_tree = std::move(item->layer_tree); @@ -205,7 +205,7 @@ DrawStatus Rasterizer::Draw(const std::shared_ptr& pipeline, std::move(item->frame_timings_recorder); float device_pixel_ratio = item->device_pixel_ratio; if (discard_callback(*layer_tree.get())) { - raster_status = RasterStatus::kDiscarded; + raster_status = DoDrawStatus::kDiscarded; } else { raster_status = DoDraw(std::move(frame_timings_recorder), std::move(layer_tree), device_pixel_ratio); @@ -230,7 +230,7 @@ DrawStatus Rasterizer::Draw(const std::shared_ptr& pipeline, if (result.success) { consume_result = PipelineConsumeResult::MoreAvailable; } - } else if (raster_status == RasterStatus::kEnqueuePipeline) { + } else if (raster_status == DoDrawStatus::kEnqueuePipeline) { consume_result = PipelineConsumeResult::MoreAvailable; } @@ -260,18 +260,18 @@ DrawStatus Rasterizer::Draw(const std::shared_ptr& pipeline, } switch (raster_status) { - case RasterStatus::kDiscarded: + case DoDrawStatus::kDiscarded: return DrawStatus::kDiscarded; - case RasterStatus::kFailed: + case DoDrawStatus::kFailed: return DrawStatus::kFailed; default: return DrawStatus::kSuccess; } } -bool Rasterizer::ShouldResubmitFrame(const RasterStatus& raster_status) { - return raster_status == RasterStatus::kResubmit || - raster_status == RasterStatus::kSkipAndRetry; +bool Rasterizer::ShouldResubmitFrame(const DoDrawStatus& raster_status) { + return raster_status == DoDrawStatus::kResubmit || + raster_status == DoDrawStatus::kSkipAndRetry; } bool Rasterizer::ShouldResubmitSurface( @@ -393,7 +393,7 @@ fml::Milliseconds Rasterizer::GetFrameBudget() const { return delegate_.GetFrameBudget(); }; -RasterStatus Rasterizer::DoDraw( +Rasterizer::DoDrawStatus Rasterizer::DoDraw( std::unique_ptr frame_timings_recorder, std::unique_ptr layer_tree, float device_pixel_ratio) { @@ -405,7 +405,7 @@ RasterStatus Rasterizer::DoDraw( ->RunsTasksOnCurrentThread()); if (!layer_tree || !surface_) { - return RasterStatus::kFailed; + return DoDrawStatus::kFailed; } PersistentCache* persistent_cache = PersistentCache::GetCacheForProcess(); @@ -422,12 +422,12 @@ RasterStatus Rasterizer::DoDraw( resubmitted_recorder_ = frame_timings_recorder->CloneUntil( FrameTimingsRecorder::State::kBuildEnd); if (draw_surface_status == DrawSurfaceStatus::kResubmit) { - return RasterStatus::kResubmit; + return DoDrawStatus::kResubmit; } else { - return RasterStatus::kSkipAndRetry; + return DoDrawStatus::kSkipAndRetry; } } else if (draw_surface_status == DrawSurfaceStatus::kDiscarded) { - return RasterStatus::kDiscarded; + return DoDrawStatus::kDiscarded; } FML_DCHECK(draw_surface_status == DrawSurfaceStatus::kSuccess || draw_surface_status == DrawSurfaceStatus::kFailed); @@ -497,14 +497,14 @@ RasterStatus Rasterizer::DoDraw( if (raster_thread_merger_) { if (raster_thread_merger_->DecrementLease() == fml::RasterThreadStatus::kUnmergedNow) { - return RasterStatus::kEnqueuePipeline; + return DoDrawStatus::kEnqueuePipeline; } } if (draw_surface_status == DrawSurfaceStatus::kSuccess) { - return RasterStatus::kSuccess; + return DoDrawStatus::kSuccess; } else { - return RasterStatus::kFailed; + return DoDrawStatus::kFailed; } } @@ -620,12 +620,12 @@ Rasterizer::DrawSurfaceStatus Rasterizer::DrawToSurfaceUnsafe( ignore_raster_cache = false; } - FrameStatus frame_status = + RasterStatus frame_status = compositor_frame->Raster(layer_tree, // layer tree ignore_raster_cache, // ignore raster cache damage.get() // frame damage ); - if (frame_status == FrameStatus::kSkipAndRetry) { + if (frame_status == RasterStatus::kSkipAndRetry) { return DrawSurfaceStatus::kSkipAndRetry; } @@ -656,7 +656,7 @@ Rasterizer::DrawSurfaceStatus Rasterizer::DrawToSurfaceUnsafe( // Do not update raster cache metrics for kResubmit because that status // indicates that the frame was not actually painted. - if (frame_status != FrameStatus::kResubmit) { + if (frame_status != RasterStatus::kResubmit) { compositor_context_->raster_cache().EndFrame(); } @@ -668,7 +668,7 @@ Rasterizer::DrawSurfaceStatus Rasterizer::DrawToSurfaceUnsafe( surface_->GetContext()->performDeferredCleanup(kSkiaCleanupExpiration); } - if (frame_status == FrameStatus::kResubmit) { + if (frame_status == RasterStatus::kResubmit) { return DrawSurfaceStatus::kResubmit; } else { return DrawSurfaceStatus::kSuccess; diff --git a/shell/common/rasterizer.h b/shell/common/rasterizer.h index 62709c34ee3e9..420e5b6b0ac62 100644 --- a/shell/common/rasterizer.h +++ b/shell/common/rasterizer.h @@ -510,9 +510,9 @@ class Rasterizer final : public SnapshotDelegate, void DisableThreadMergerIfNeeded(); private: - using FrameStatus = CompositorContext::FrameStatus; + using RasterStatus = RasterStatus; - enum DrawSurfaceStatus { + enum class DrawSurfaceStatus { // Frame has been successfully rasterized. kSuccess, // Frame is submitted twice. This is only used on Android when @@ -538,6 +538,37 @@ class Rasterizer final : public SnapshotDelegate, kDiscarded, }; + enum class DoDrawStatus { + // Frame has been successfully rasterized. + kSuccess, + // Frame is submitted twice. This is only used on Android when + // switching the background surface to FlutterImageView. + // + // On Android, the first frame doesn't make the image available + // to the ImageReader right away. The second frame does. + // + // TODO(egarciad): https://github.com/flutter/flutter/issues/65652 + kResubmit, + // Frame is dropped and a new frame with the same layer tree is + // attempted. + // + // This is currently used to wait for the thread merger to merge + // the raster and platform threads. + // + // Since the thread merger may be disabled, + kSkipAndRetry, + // Frame has been successfully rasterized, but "there are additional items + // in + // the pipeline waiting to be consumed. This is currently + // only used when thread configuration change occurs. + kEnqueuePipeline, + // Failed to rasterize the frame. + kFailed, + // Layer tree was discarded due to LayerTreeDiscardCallback or inability to + // access the GPU. + kDiscarded, + }; + // |SnapshotDelegate| std::unique_ptr MakeSkiaGpuImage( sk_sp display_list, @@ -592,7 +623,7 @@ class Rasterizer final : public SnapshotDelegate, GrDirectContext* surface_context, bool compressed); - RasterStatus DoDraw( + DoDrawStatus DoDraw( std::unique_ptr frame_timings_recorder, std::unique_ptr layer_tree, float device_pixel_ratio); @@ -609,7 +640,7 @@ class Rasterizer final : public SnapshotDelegate, void FireNextFrameCallbackIfPresent(); static bool NoDiscard(const flutter::LayerTree& layer_tree) { return false; } - static bool ShouldResubmitFrame(const RasterStatus& raster_status); + static bool ShouldResubmitFrame(const DoDrawStatus& raster_status); static bool ShouldResubmitSurface( const DrawSurfaceStatus& draw_surface_status); From 1138ada4a0a314dcdd1f40e10fcd6c07882aaa6e Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Wed, 16 Aug 2023 22:46:24 -0700 Subject: [PATCH 05/48] Combine retry --- shell/common/rasterizer.cc | 40 ++++++++++-------------------- shell/common/rasterizer.h | 50 +++++++++++++------------------------- 2 files changed, 30 insertions(+), 60 deletions(-) diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index ada57268df03a..2680404b770e6 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -178,7 +178,8 @@ void Rasterizer::DrawLastLayerTree( // EndFrame should perform cleanups for the external_view_embedder. if (external_view_embedder_ && external_view_embedder_->GetUsedThisFrame()) { - bool should_resubmit_frame = ShouldResubmitSurface(draw_surface_status); + bool should_resubmit_frame = + draw_surface_status == DrawSurfaceStatus::kRetry; external_view_embedder_->SetUsedThisFrame(false); external_view_embedder_->EndFrame(should_resubmit_frame, raster_thread_merger_); @@ -197,7 +198,7 @@ DrawStatus Rasterizer::Draw(const std::shared_ptr& pipeline, .GetRasterTaskRunner() ->RunsTasksOnCurrentThread()); - DoDrawStatus raster_status = DoDrawStatus::kFailed; + DoDrawStatus do_draw_status = DoDrawStatus::kFailed; LayerTreePipeline::Consumer consumer = [&](std::unique_ptr item) { std::unique_ptr layer_tree = std::move(item->layer_tree); @@ -205,10 +206,10 @@ DrawStatus Rasterizer::Draw(const std::shared_ptr& pipeline, std::move(item->frame_timings_recorder); float device_pixel_ratio = item->device_pixel_ratio; if (discard_callback(*layer_tree.get())) { - raster_status = DoDrawStatus::kDiscarded; + do_draw_status = DoDrawStatus::kDiscarded; } else { - raster_status = DoDraw(std::move(frame_timings_recorder), - std::move(layer_tree), device_pixel_ratio); + do_draw_status = DoDraw(std::move(frame_timings_recorder), + std::move(layer_tree), device_pixel_ratio); } }; @@ -219,7 +220,7 @@ DrawStatus Rasterizer::Draw(const std::shared_ptr& pipeline, // if the raster status is to resubmit the frame, we push the frame to the // front of the queue and also change the consume status to more available. - bool should_resubmit_frame = ShouldResubmitFrame(raster_status); + bool should_resubmit_frame = do_draw_status == DoDrawStatus::kRetry; if (should_resubmit_frame) { auto resubmitted_layer_tree_item = std::make_unique( std::move(resubmitted_layer_tree_), std::move(resubmitted_recorder_), @@ -230,7 +231,7 @@ DrawStatus Rasterizer::Draw(const std::shared_ptr& pipeline, if (result.success) { consume_result = PipelineConsumeResult::MoreAvailable; } - } else if (raster_status == DoDrawStatus::kEnqueuePipeline) { + } else if (do_draw_status == DoDrawStatus::kEnqueuePipeline) { consume_result = PipelineConsumeResult::MoreAvailable; } @@ -259,7 +260,7 @@ DrawStatus Rasterizer::Draw(const std::shared_ptr& pipeline, break; } - switch (raster_status) { + switch (do_draw_status) { case DoDrawStatus::kDiscarded: return DrawStatus::kDiscarded; case DoDrawStatus::kFailed: @@ -269,17 +270,6 @@ DrawStatus Rasterizer::Draw(const std::shared_ptr& pipeline, } } -bool Rasterizer::ShouldResubmitFrame(const DoDrawStatus& raster_status) { - return raster_status == DoDrawStatus::kResubmit || - raster_status == DoDrawStatus::kSkipAndRetry; -} - -bool Rasterizer::ShouldResubmitSurface( - const DrawSurfaceStatus& draw_surface_status) { - return draw_surface_status == DrawSurfaceStatus::kResubmit || - draw_surface_status == DrawSurfaceStatus::kSkipAndRetry; -} - namespace { std::unique_ptr MakeBitmapImage( const sk_sp& display_list, @@ -416,16 +406,12 @@ Rasterizer::DoDrawStatus Rasterizer::DoDraw( if (draw_surface_status == DrawSurfaceStatus::kSuccess) { last_layer_tree_ = std::move(layer_tree); last_device_pixel_ratio_ = device_pixel_ratio; - } else if (ShouldResubmitSurface(draw_surface_status)) { + } else if (draw_surface_status == DrawSurfaceStatus::kRetry) { resubmitted_pixel_ratio_ = device_pixel_ratio; resubmitted_layer_tree_ = std::move(layer_tree); resubmitted_recorder_ = frame_timings_recorder->CloneUntil( FrameTimingsRecorder::State::kBuildEnd); - if (draw_surface_status == DrawSurfaceStatus::kResubmit) { - return DoDrawStatus::kResubmit; - } else { - return DoDrawStatus::kSkipAndRetry; - } + return DoDrawStatus::kRetry; } else if (draw_surface_status == DrawSurfaceStatus::kDiscarded) { return DoDrawStatus::kDiscarded; } @@ -626,7 +612,7 @@ Rasterizer::DrawSurfaceStatus Rasterizer::DrawToSurfaceUnsafe( damage.get() // frame damage ); if (frame_status == RasterStatus::kSkipAndRetry) { - return DrawSurfaceStatus::kSkipAndRetry; + return DrawSurfaceStatus::kRetry; } SurfaceFrame::SubmitInfo submit_info; @@ -669,7 +655,7 @@ Rasterizer::DrawSurfaceStatus Rasterizer::DrawToSurfaceUnsafe( } if (frame_status == RasterStatus::kResubmit) { - return DrawSurfaceStatus::kResubmit; + return DrawSurfaceStatus::kRetry; } else { return DrawSurfaceStatus::kSuccess; } diff --git a/shell/common/rasterizer.h b/shell/common/rasterizer.h index 420e5b6b0ac62..ff3a17d32b029 100644 --- a/shell/common/rasterizer.h +++ b/shell/common/rasterizer.h @@ -515,22 +515,16 @@ class Rasterizer final : public SnapshotDelegate, enum class DrawSurfaceStatus { // Frame has been successfully rasterized. kSuccess, - // Frame is submitted twice. This is only used on Android when - // switching the background surface to FlutterImageView. - // - // On Android, the first frame doesn't make the image available - // to the ImageReader right away. The second frame does. + // Frame should be submitted again. // + // This can occur on Android when switching the background surface to + // FlutterImageView. On Android, the first frame doesn't make the image + // available to the ImageReader right away. The second frame does. // TODO(egarciad): https://github.com/flutter/flutter/issues/65652 - kResubmit, - // Frame is dropped and a new frame with the same layer tree is - // attempted. - // - // This is currently used to wait for the thread merger to merge - // the raster and platform threads. // - // Since the thread merger may be disabled, - kSkipAndRetry, + // This can also occur when the frame is dropped to wait for the thread + // merger to merge the raster and platform threads. + kRetry, // Failed to rasterize the frame. kFailed, // Layer tree was discarded due to LayerTreeDiscardCallback or inability to @@ -541,26 +535,19 @@ class Rasterizer final : public SnapshotDelegate, enum class DoDrawStatus { // Frame has been successfully rasterized. kSuccess, - // Frame is submitted twice. This is only used on Android when - // switching the background surface to FlutterImageView. - // - // On Android, the first frame doesn't make the image available - // to the ImageReader right away. The second frame does. + // Frame should be submitted again. // + // This can occur on Android when switching the background surface to + // FlutterImageView. On Android, the first frame doesn't make the image + // available to the ImageReader right away. The second frame does. // TODO(egarciad): https://github.com/flutter/flutter/issues/65652 - kResubmit, - // Frame is dropped and a new frame with the same layer tree is - // attempted. - // - // This is currently used to wait for the thread merger to merge - // the raster and platform threads. // - // Since the thread merger may be disabled, - kSkipAndRetry, - // Frame has been successfully rasterized, but "there are additional items - // in - // the pipeline waiting to be consumed. This is currently - // only used when thread configuration change occurs. + // This can also occur when the frame is dropped to wait for the thread + // merger to merge the raster and platform threads. + kRetry, + // Frame has been successfully rasterized, but there are additional items + // in the pipeline waiting to be consumed. This is currently only used when + // thread configuration change occurs. kEnqueuePipeline, // Failed to rasterize the frame. kFailed, @@ -640,9 +627,6 @@ class Rasterizer final : public SnapshotDelegate, void FireNextFrameCallbackIfPresent(); static bool NoDiscard(const flutter::LayerTree& layer_tree) { return false; } - static bool ShouldResubmitFrame(const DoDrawStatus& raster_status); - static bool ShouldResubmitSurface( - const DrawSurfaceStatus& draw_surface_status); Delegate& delegate_; MakeGpuImageBehavior gpu_image_behavior_; From 682681866b34988de5911caad1f2d4fd536a9a9c Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Thu, 17 Aug 2023 00:04:34 -0700 Subject: [PATCH 06/48] Split status, found one --- shell/common/rasterizer.cc | 4 ++-- shell/common/rasterizer.h | 2 ++ shell/common/rasterizer_unittests.cc | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index 2680404b770e6..968ec91303a8e 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -192,7 +192,7 @@ DrawStatus Rasterizer::Draw(const std::shared_ptr& pipeline, if (raster_thread_merger_ && !raster_thread_merger_->IsOnRasterizingThread()) { // we yield and let this frame be serviced on the right thread. - return DrawStatus::kFailed; + return DrawStatus::kWrongThread; } FML_DCHECK(delegate_.GetTaskRunners() .GetRasterTaskRunner() @@ -215,7 +215,7 @@ DrawStatus Rasterizer::Draw(const std::shared_ptr& pipeline, PipelineConsumeResult consume_result = pipeline->Consume(consumer); if (consume_result == PipelineConsumeResult::NoneAvailable) { - return DrawStatus::kFailed; + return DrawStatus::kPipelineUnavailable; } // if the raster status is to resubmit the frame, we push the frame to the // front of the queue and also change the consume status to more available. diff --git a/shell/common/rasterizer.h b/shell/common/rasterizer.h index ff3a17d32b029..ff3ef8faa7f8a 100644 --- a/shell/common/rasterizer.h +++ b/shell/common/rasterizer.h @@ -55,6 +55,8 @@ enum class DrawStatus { // Layer tree was discarded due to LayerTreeDiscardCallback or inability to // access the GPU. kDiscarded, + kWrongThread, + kPipelineUnavailable, }; //------------------------------------------------------------------------------ diff --git a/shell/common/rasterizer_unittests.cc b/shell/common/rasterizer_unittests.cc index c24a8c08abd7d..7ccf863801604 100644 --- a/shell/common/rasterizer_unittests.cc +++ b/shell/common/rasterizer_unittests.cc @@ -563,7 +563,7 @@ TEST(RasterizerTest, externalViewEmbedderDoesntEndFrameWhenPipelineIsEmpty) { auto pipeline = std::make_shared(/*depth=*/10); auto no_discard = [](LayerTree&) { return false; }; DrawStatus status = rasterizer->Draw(pipeline, no_discard); - EXPECT_EQ(status, DrawStatus::kFailed); + EXPECT_EQ(status, DrawStatus::kPipelineUnavailable); latch.Signal(); }); latch.Wait(); From 6d64314fc55bacbb30ddf15105ce165159d28e32 Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Thu, 17 Aug 2023 01:05:44 -0700 Subject: [PATCH 07/48] Add doc --- flow/compositor_context.h | 7 ++++--- shell/common/rasterizer.cc | 10 +++++++--- shell/common/rasterizer.h | 10 ++++++++-- shell/common/rasterizer_unittests.cc | 2 +- 4 files changed, 20 insertions(+), 9 deletions(-) diff --git a/flow/compositor_context.h b/flow/compositor_context.h index 309cbde87502d..7bb16918f2d38 100644 --- a/flow/compositor_context.h +++ b/flow/compositor_context.h @@ -23,18 +23,19 @@ namespace flutter { class LayerTree; +// The result status of CompositorContext::ScopedFrame::Raster. enum class RasterStatus { // Frame has been successfully rasterized. kSuccess, - // Frame should be submitted twice. This is only used on Android when - // switching the background surface to FlutterImageView. + // Frame has been submited, but should be submitted again. This is only used + // on Android when switching the background surface to FlutterImageView. // // On Android, the first frame doesn't make the image available // to the ImageReader right away. The second frame does. // // TODO(egarciad): https://github.com/flutter/flutter/issues/65652 kResubmit, - // Frame is dropped and a new frame with the same layer tree should be + // Frame should be dropped and a new frame with the same layer tree should be // attempted. // // This is currently used to wait for the thread merger to merge diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index 968ec91303a8e..d3a1eb98ba015 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -192,13 +192,13 @@ DrawStatus Rasterizer::Draw(const std::shared_ptr& pipeline, if (raster_thread_merger_ && !raster_thread_merger_->IsOnRasterizingThread()) { // we yield and let this frame be serviced on the right thread. - return DrawStatus::kWrongThread; + return DrawStatus::kYielded; } FML_DCHECK(delegate_.GetTaskRunners() .GetRasterTaskRunner() ->RunsTasksOnCurrentThread()); - DoDrawStatus do_draw_status = DoDrawStatus::kFailed; + DoDrawStatus do_draw_status = DoDrawStatus::kSuccess; LayerTreePipeline::Consumer consumer = [&](std::unique_ptr item) { std::unique_ptr layer_tree = std::move(item->layer_tree); @@ -215,7 +215,7 @@ DrawStatus Rasterizer::Draw(const std::shared_ptr& pipeline, PipelineConsumeResult consume_result = pipeline->Consume(consumer); if (consume_result == PipelineConsumeResult::NoneAvailable) { - return DrawStatus::kPipelineUnavailable; + return DrawStatus::kPipelineNoneAvailable; } // if the raster status is to resubmit the frame, we push the frame to the // front of the queue and also change the consume status to more available. @@ -261,6 +261,8 @@ DrawStatus Rasterizer::Draw(const std::shared_ptr& pipeline, } switch (do_draw_status) { + case DoDrawStatus::kEmpty: + return DrawStatus::kEmpty; case DoDrawStatus::kDiscarded: return DrawStatus::kDiscarded; case DoDrawStatus::kFailed: @@ -551,6 +553,8 @@ Rasterizer::DrawSurfaceStatus Rasterizer::DrawToSurfaceUnsafe( if (frame == nullptr) { frame_timings_recorder.RecordRasterEnd( &compositor_context_->raster_cache()); + printf("frame empty\n"); + fflush(stdout); return DrawSurfaceStatus::kFailed; } diff --git a/shell/common/rasterizer.h b/shell/common/rasterizer.h index ff3ef8faa7f8a..392419eed600c 100644 --- a/shell/common/rasterizer.h +++ b/shell/common/rasterizer.h @@ -47,6 +47,7 @@ class AiksContext; namespace flutter { +// The result status of Rasterizer::DoDraw. This is only used for unit tests. enum class DrawStatus { // Frame has been successfully rasterized. kSuccess, @@ -55,8 +56,11 @@ enum class DrawStatus { // Layer tree was discarded due to LayerTreeDiscardCallback or inability to // access the GPU. kDiscarded, - kWrongThread, - kPipelineUnavailable, + // Nothing was done, because the call was not on the raster thread. Yielded to + // let this frame be serviced on the right thread. + kYielded, + // Nothing was done, because pipeline has nothing in queue. + kPipelineNoneAvailable, }; //------------------------------------------------------------------------------ @@ -514,6 +518,7 @@ class Rasterizer final : public SnapshotDelegate, private: using RasterStatus = RasterStatus; + // The result status of DrawToSurface and DrawToSurfaceUnsafe. enum class DrawSurfaceStatus { // Frame has been successfully rasterized. kSuccess, @@ -534,6 +539,7 @@ class Rasterizer final : public SnapshotDelegate, kDiscarded, }; + // The result status of DoDraw. enum class DoDrawStatus { // Frame has been successfully rasterized. kSuccess, diff --git a/shell/common/rasterizer_unittests.cc b/shell/common/rasterizer_unittests.cc index 7ccf863801604..7e3b4dc1abe9c 100644 --- a/shell/common/rasterizer_unittests.cc +++ b/shell/common/rasterizer_unittests.cc @@ -563,7 +563,7 @@ TEST(RasterizerTest, externalViewEmbedderDoesntEndFrameWhenPipelineIsEmpty) { auto pipeline = std::make_shared(/*depth=*/10); auto no_discard = [](LayerTree&) { return false; }; DrawStatus status = rasterizer->Draw(pipeline, no_discard); - EXPECT_EQ(status, DrawStatus::kPipelineUnavailable); + EXPECT_EQ(status, DrawStatus::kPipelineNoneAvailable); latch.Signal(); }); latch.Wait(); From 07dfb2f54b89336ef10c52f45b625dd54888d7c9 Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Thu, 17 Aug 2023 01:20:09 -0700 Subject: [PATCH 08/48] Split gpu unavailable --- shell/common/rasterizer.cc | 13 ++++++++----- shell/common/rasterizer.h | 8 ++++++-- shell/common/rasterizer_unittests.cc | 4 ++-- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index d3a1eb98ba015..c1b297db46a4b 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -215,7 +215,7 @@ DrawStatus Rasterizer::Draw(const std::shared_ptr& pipeline, PipelineConsumeResult consume_result = pipeline->Consume(consumer); if (consume_result == PipelineConsumeResult::NoneAvailable) { - return DrawStatus::kPipelineNoneAvailable; + return DrawStatus::kPipelineEmpty; } // if the raster status is to resubmit the frame, we push the frame to the // front of the queue and also change the consume status to more available. @@ -261,8 +261,8 @@ DrawStatus Rasterizer::Draw(const std::shared_ptr& pipeline, } switch (do_draw_status) { - case DoDrawStatus::kEmpty: - return DrawStatus::kEmpty; + case DoDrawStatus::kGpuUnavailable: + return DrawStatus::kGpuUnavailable; case DoDrawStatus::kDiscarded: return DrawStatus::kDiscarded; case DoDrawStatus::kFailed: @@ -416,6 +416,8 @@ Rasterizer::DoDrawStatus Rasterizer::DoDraw( return DoDrawStatus::kRetry; } else if (draw_surface_status == DrawSurfaceStatus::kDiscarded) { return DoDrawStatus::kDiscarded; + } else if (draw_surface_status == DrawSurfaceStatus::kGpuUnavailable) { + return DoDrawStatus::kGpuUnavailable; } FML_DCHECK(draw_surface_status == DrawSurfaceStatus::kSuccess || draw_surface_status == DrawSurfaceStatus::kFailed); @@ -510,8 +512,9 @@ Rasterizer::DrawSurfaceStatus Rasterizer::DrawToSurface( } else { delegate_.GetIsGpuDisabledSyncSwitch()->Execute( fml::SyncSwitch::Handlers() - .SetIfTrue( - [&] { draw_surface_status = DrawSurfaceStatus::kDiscarded; }) + .SetIfTrue([&] { + draw_surface_status = DrawSurfaceStatus::kGpuUnavailable; + }) .SetIfFalse([&] { draw_surface_status = DrawToSurfaceUnsafe( frame_timings_recorder, layer_tree, device_pixel_ratio); diff --git a/shell/common/rasterizer.h b/shell/common/rasterizer.h index 392419eed600c..4d9aa545a3a81 100644 --- a/shell/common/rasterizer.h +++ b/shell/common/rasterizer.h @@ -59,8 +59,10 @@ enum class DrawStatus { // Nothing was done, because the call was not on the raster thread. Yielded to // let this frame be serviced on the right thread. kYielded, - // Nothing was done, because pipeline has nothing in queue. - kPipelineNoneAvailable, + // Nothing was done, because pipeline was empty. + kPipelineEmpty, + // Nothing was done, because GPU was unavailable. + kGpuUnavailable, }; //------------------------------------------------------------------------------ @@ -537,6 +539,7 @@ class Rasterizer final : public SnapshotDelegate, // Layer tree was discarded due to LayerTreeDiscardCallback or inability to // access the GPU. kDiscarded, + kGpuUnavailable, }; // The result status of DoDraw. @@ -562,6 +565,7 @@ class Rasterizer final : public SnapshotDelegate, // Layer tree was discarded due to LayerTreeDiscardCallback or inability to // access the GPU. kDiscarded, + kGpuUnavailable, }; // |SnapshotDelegate| diff --git a/shell/common/rasterizer_unittests.cc b/shell/common/rasterizer_unittests.cc index 7e3b4dc1abe9c..d19badb275dba 100644 --- a/shell/common/rasterizer_unittests.cc +++ b/shell/common/rasterizer_unittests.cc @@ -563,7 +563,7 @@ TEST(RasterizerTest, externalViewEmbedderDoesntEndFrameWhenPipelineIsEmpty) { auto pipeline = std::make_shared(/*depth=*/10); auto no_discard = [](LayerTree&) { return false; }; DrawStatus status = rasterizer->Draw(pipeline, no_discard); - EXPECT_EQ(status, DrawStatus::kPipelineNoneAvailable); + EXPECT_EQ(status, DrawStatus::kPipelineEmpty); latch.Signal(); }); latch.Wait(); @@ -794,7 +794,7 @@ TEST( EXPECT_TRUE(result.success); auto no_discard = [](LayerTree&) { return false; }; DrawStatus status = rasterizer->Draw(pipeline, no_discard); - EXPECT_EQ(status, DrawStatus::kDiscarded); + EXPECT_EQ(status, DrawStatus::kGpuUnavailable); latch.Signal(); }); latch.Wait(); From 4375281fad2b6fb355a5e7c5b134f07638f481f2 Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Thu, 17 Aug 2023 08:56:12 -0700 Subject: [PATCH 09/48] Remove DrawSurfaceStatus discarded --- shell/common/rasterizer.cc | 4 ---- shell/common/rasterizer.h | 11 ++++------- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index c1b297db46a4b..6122916dab043 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -414,8 +414,6 @@ Rasterizer::DoDrawStatus Rasterizer::DoDraw( resubmitted_recorder_ = frame_timings_recorder->CloneUntil( FrameTimingsRecorder::State::kBuildEnd); return DoDrawStatus::kRetry; - } else if (draw_surface_status == DrawSurfaceStatus::kDiscarded) { - return DoDrawStatus::kDiscarded; } else if (draw_surface_status == DrawSurfaceStatus::kGpuUnavailable) { return DoDrawStatus::kGpuUnavailable; } @@ -556,8 +554,6 @@ Rasterizer::DrawSurfaceStatus Rasterizer::DrawToSurfaceUnsafe( if (frame == nullptr) { frame_timings_recorder.RecordRasterEnd( &compositor_context_->raster_cache()); - printf("frame empty\n"); - fflush(stdout); return DrawSurfaceStatus::kFailed; } diff --git a/shell/common/rasterizer.h b/shell/common/rasterizer.h index 4d9aa545a3a81..785c84e18f679 100644 --- a/shell/common/rasterizer.h +++ b/shell/common/rasterizer.h @@ -53,8 +53,7 @@ enum class DrawStatus { kSuccess, // Failed to rasterize the frame. kFailed, - // Layer tree was discarded due to LayerTreeDiscardCallback or inability to - // access the GPU. + // Layer tree was discarded due to LayerTreeDiscardCallback. kDiscarded, // Nothing was done, because the call was not on the raster thread. Yielded to // let this frame be serviced on the right thread. @@ -536,9 +535,7 @@ class Rasterizer final : public SnapshotDelegate, kRetry, // Failed to rasterize the frame. kFailed, - // Layer tree was discarded due to LayerTreeDiscardCallback or inability to - // access the GPU. - kDiscarded, + // Layer tree was discarded due to inability to access the GPU. kGpuUnavailable, }; @@ -562,9 +559,9 @@ class Rasterizer final : public SnapshotDelegate, kEnqueuePipeline, // Failed to rasterize the frame. kFailed, - // Layer tree was discarded due to LayerTreeDiscardCallback or inability to - // access the GPU. + // Layer tree was discarded due to LayerTreeDiscardCallback. kDiscarded, + // Layer tree was discarded due to inability to access the GPU. kGpuUnavailable, }; From 1b980ad9457a1a9d32203585984b0fbd5ca54901 Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Thu, 17 Aug 2023 14:11:40 -0700 Subject: [PATCH 10/48] Move the discard callback to surface --- shell/common/rasterizer.cc | 45 ++++++++++++++++++++++++-------------- shell/common/rasterizer.h | 7 +++++- 2 files changed, 35 insertions(+), 17 deletions(-) diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index 81049db056962..e638b5edd3ba0 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -182,8 +182,12 @@ void Rasterizer::DrawLastLayerTree( if (!last_layer_tree_ || !surface_) { return; } - DrawSurfaceStatus draw_surface_status = DrawToSurface( - *frame_timings_recorder, *last_layer_tree_, last_device_pixel_ratio_); + LayerTreeDiscardCallback no_discard = [](int64_t, flutter::LayerTree&) { + return false; + }; + DrawSurfaceStatus draw_surface_status = + DrawToSurface(no_discard, *frame_timings_recorder, *last_layer_tree_, + last_device_pixel_ratio_); // EndFrame should perform cleanups for the external_view_embedder. if (external_view_embedder_ && external_view_embedder_->GetUsedThisFrame()) { @@ -210,19 +214,13 @@ DrawStatus Rasterizer::Draw(const std::shared_ptr& pipeline, DoDrawStatus do_draw_status = DoDrawStatus::kSuccess; LayerTreePipeline::Consumer consumer = [&](std::unique_ptr item) { - // TODO(dkwingsmt): Use a proper view ID when Rasterizer supports - // multi-view. - int64_t view_id = kFlutterImplicitViewId; std::unique_ptr layer_tree = std::move(item->layer_tree); std::unique_ptr frame_timings_recorder = std::move(item->frame_timings_recorder); float device_pixel_ratio = item->device_pixel_ratio; - if (discard_callback(view_id, *layer_tree.get())) { - do_draw_status = DoDrawStatus::kDiscarded; - } else { - do_draw_status = DoDraw(std::move(frame_timings_recorder), - std::move(layer_tree), device_pixel_ratio); - } + do_draw_status = + DoDraw(discard_callback, std::move(frame_timings_recorder), + std::move(layer_tree), device_pixel_ratio); }; PipelineConsumeResult consume_result = pipeline->Consume(consumer); @@ -398,6 +396,7 @@ fml::Milliseconds Rasterizer::GetFrameBudget() const { }; Rasterizer::DoDrawStatus Rasterizer::DoDraw( + LayerTreeDiscardCallback& discard_callback, std::unique_ptr frame_timings_recorder, std::unique_ptr layer_tree, float device_pixel_ratio) { @@ -416,7 +415,8 @@ Rasterizer::DoDrawStatus Rasterizer::DoDraw( persistent_cache->ResetStoredNewShaders(); DrawSurfaceStatus draw_surface_status = - DrawToSurface(*frame_timings_recorder, *layer_tree, device_pixel_ratio); + DrawToSurface(discard_callback, *frame_timings_recorder, *layer_tree, + device_pixel_ratio); if (draw_surface_status == DrawSurfaceStatus::kSuccess) { last_layer_tree_ = std::move(layer_tree); last_device_pixel_ratio_ = device_pixel_ratio; @@ -428,6 +428,8 @@ Rasterizer::DoDrawStatus Rasterizer::DoDraw( return DoDrawStatus::kRetry; } else if (draw_surface_status == DrawSurfaceStatus::kGpuUnavailable) { return DoDrawStatus::kGpuUnavailable; + } else if (draw_surface_status == DrawSurfaceStatus::kDiscarded) { + return DoDrawStatus::kDiscarded; } FML_DCHECK(draw_surface_status == DrawSurfaceStatus::kSuccess || draw_surface_status == DrawSurfaceStatus::kFailed); @@ -509,6 +511,7 @@ Rasterizer::DoDrawStatus Rasterizer::DoDraw( } Rasterizer::DrawSurfaceStatus Rasterizer::DrawToSurface( + LayerTreeDiscardCallback& discard_callback, FrameTimingsRecorder& frame_timings_recorder, flutter::LayerTree& layer_tree, float device_pixel_ratio) { @@ -517,8 +520,9 @@ Rasterizer::DrawSurfaceStatus Rasterizer::DrawToSurface( DrawSurfaceStatus draw_surface_status; if (surface_->AllowsDrawingWhenGpuDisabled()) { - draw_surface_status = DrawToSurfaceUnsafe(frame_timings_recorder, - layer_tree, device_pixel_ratio); + draw_surface_status = + DrawToSurfaceUnsafe(discard_callback, frame_timings_recorder, + layer_tree, device_pixel_ratio); } else { delegate_.GetIsGpuDisabledSyncSwitch()->Execute( fml::SyncSwitch::Handlers() @@ -526,8 +530,9 @@ Rasterizer::DrawSurfaceStatus Rasterizer::DrawToSurface( draw_surface_status = DrawSurfaceStatus::kGpuUnavailable; }) .SetIfFalse([&] { - draw_surface_status = DrawToSurfaceUnsafe( - frame_timings_recorder, layer_tree, device_pixel_ratio); + draw_surface_status = + DrawToSurfaceUnsafe(discard_callback, frame_timings_recorder, + layer_tree, device_pixel_ratio); })); } @@ -538,11 +543,19 @@ Rasterizer::DrawSurfaceStatus Rasterizer::DrawToSurface( /// when iOS is backgrounded, for example. /// \see Rasterizer::DrawToSurface Rasterizer::DrawSurfaceStatus Rasterizer::DrawToSurfaceUnsafe( + LayerTreeDiscardCallback& discard_callback, FrameTimingsRecorder& frame_timings_recorder, flutter::LayerTree& layer_tree, float device_pixel_ratio) { FML_DCHECK(surface_); + // TODO(dkwingsmt): Use a proper view ID when Rasterizer supports + // multi-view. + int64_t view_id = kFlutterImplicitViewId; + if (discard_callback(view_id, layer_tree)) { + return DrawSurfaceStatus::kDiscarded; + } + compositor_context_->ui_time().SetLapTime( frame_timings_recorder.GetBuildDuration()); diff --git a/shell/common/rasterizer.h b/shell/common/rasterizer.h index 4a461d4466bc6..7e3ca604a69fd 100644 --- a/shell/common/rasterizer.h +++ b/shell/common/rasterizer.h @@ -549,6 +549,8 @@ class Rasterizer final : public SnapshotDelegate, kRetry, // Failed to rasterize the frame. kFailed, + // Layer tree was discarded due to LayerTreeDiscardCallback. + kDiscarded, // Layer tree was discarded due to inability to access the GPU. kGpuUnavailable, }; @@ -634,15 +636,18 @@ class Rasterizer final : public SnapshotDelegate, bool compressed); DoDrawStatus DoDraw( + LayerTreeDiscardCallback& discard_callback, std::unique_ptr frame_timings_recorder, std::unique_ptr layer_tree, float device_pixel_ratio); - DrawSurfaceStatus DrawToSurface(FrameTimingsRecorder& frame_timings_recorder, + DrawSurfaceStatus DrawToSurface(LayerTreeDiscardCallback& discard_callback, + FrameTimingsRecorder& frame_timings_recorder, flutter::LayerTree& layer_tree, float device_pixel_ratio); DrawSurfaceStatus DrawToSurfaceUnsafe( + LayerTreeDiscardCallback& discard_callback, FrameTimingsRecorder& frame_timings_recorder, flutter::LayerTree& layer_tree, float device_pixel_ratio); From 4618ad7d09bd78e6897c2c450779202932f24404 Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Tue, 22 Aug 2023 23:31:13 -0700 Subject: [PATCH 11/48] Move up discarding --- shell/common/rasterizer.cc | 14 +++++++------- shell/common/rasterizer.h | 2 -- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index 975762ad15eba..c3279c96d34b5 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -508,6 +508,13 @@ Rasterizer::DrawSurfaceStatus Rasterizer::DrawToSurface( TRACE_EVENT0("flutter", "Rasterizer::DrawToSurface"); FML_DCHECK(surface_); + // TODO(dkwingsmt): Use a proper view ID when Rasterizer supports + // multi-view. + int64_t view_id = kFlutterImplicitViewId; + if (delegate_.ShouldDiscardLayerTree(view_id, layer_tree)) { + return DrawSurfaceStatus::kDiscarded; + } + DrawSurfaceStatus draw_surface_status; if (surface_->AllowsDrawingWhenGpuDisabled()) { draw_surface_status = DrawToSurfaceUnsafe(frame_timings_recorder, @@ -536,13 +543,6 @@ Rasterizer::DrawSurfaceStatus Rasterizer::DrawToSurfaceUnsafe( float device_pixel_ratio) { FML_DCHECK(surface_); - // TODO(dkwingsmt): Use a proper view ID when Rasterizer supports - // multi-view. - int64_t view_id = kFlutterImplicitViewId; - if (delegate_.ShouldDiscardLayerTree(view_id, layer_tree)) { - return DrawSurfaceStatus::kDiscarded; - } - compositor_context_->ui_time().SetLapTime( frame_timings_recorder.GetBuildDuration()); diff --git a/shell/common/rasterizer.h b/shell/common/rasterizer.h index 02e7b97a507f0..0e9af89cb329d 100644 --- a/shell/common/rasterizer.h +++ b/shell/common/rasterizer.h @@ -529,8 +529,6 @@ class Rasterizer final : public SnapshotDelegate, void DisableThreadMergerIfNeeded(); private: - using RasterStatus = RasterStatus; - // The result status of DrawToSurface and DrawToSurfaceUnsafe. enum class DrawSurfaceStatus { // Frame has been successfully rasterized. From 7d1706adb2ac3aa975f33c87863a93fc4cd1f560 Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Wed, 23 Aug 2023 11:30:48 -0700 Subject: [PATCH 12/48] Better success handling --- shell/common/rasterizer.cc | 13 +++++++++---- shell/common/rasterizer.h | 2 ++ 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index c3279c96d34b5..1c2dfb1ffdd90 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -263,6 +263,10 @@ DrawStatus Rasterizer::Draw( break; } + return ToDrawStatus(do_draw_status); +} + +DrawStatus Rasterizer::ToDrawStatus(DoDrawStatus do_draw_status) { switch (do_draw_status) { case DoDrawStatus::kGpuUnavailable: return DrawStatus::kGpuUnavailable; @@ -408,10 +412,7 @@ Rasterizer::DoDrawStatus Rasterizer::DoDraw( DrawSurfaceStatus draw_surface_status = DrawToSurface(*frame_timings_recorder, *layer_tree, device_pixel_ratio); - if (draw_surface_status == DrawSurfaceStatus::kSuccess) { - last_layer_tree_ = std::move(layer_tree); - last_device_pixel_ratio_ = device_pixel_ratio; - } else if (draw_surface_status == DrawSurfaceStatus::kRetry) { + if (draw_surface_status == DrawSurfaceStatus::kRetry) { resubmitted_pixel_ratio_ = device_pixel_ratio; resubmitted_layer_tree_ = std::move(layer_tree); resubmitted_recorder_ = frame_timings_recorder->CloneUntil( @@ -424,6 +425,10 @@ Rasterizer::DoDrawStatus Rasterizer::DoDraw( } FML_DCHECK(draw_surface_status == DrawSurfaceStatus::kSuccess || draw_surface_status == DrawSurfaceStatus::kFailed); + if (draw_surface_status == DrawSurfaceStatus::kSuccess) { + last_layer_tree_ = std::move(layer_tree); + last_device_pixel_ratio_ = device_pixel_ratio; + } if (persistent_cache->IsDumpingSkp() && persistent_cache->StoredNewShaders()) { diff --git a/shell/common/rasterizer.h b/shell/common/rasterizer.h index 0e9af89cb329d..e38f4ba7aa773 100644 --- a/shell/common/rasterizer.h +++ b/shell/common/rasterizer.h @@ -648,6 +648,8 @@ class Rasterizer final : public SnapshotDelegate, void FireNextFrameCallbackIfPresent(); + static DrawStatus ToDrawStatus(DoDrawStatus do_draw_status); + Delegate& delegate_; MakeGpuImageBehavior gpu_image_behavior_; std::weak_ptr impeller_context_; From 209ebee7f32f600f24cb71e3bf95a5e1193745aa Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Wed, 23 Aug 2023 12:22:58 -0700 Subject: [PATCH 13/48] Revert the discard movement --- shell/common/rasterizer.cc | 16 +++++++--------- shell/common/rasterizer.h | 2 -- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index 1c2dfb1ffdd90..4c3f7180e5d8f 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -403,6 +403,13 @@ Rasterizer::DoDrawStatus Rasterizer::DoDraw( .GetRasterTaskRunner() ->RunsTasksOnCurrentThread()); + // TODO(dkwingsmt): Use a proper view ID when Rasterizer supports + // multi-view. + int64_t view_id = kFlutterImplicitViewId; + if (delegate_.ShouldDiscardLayerTree(view_id, *layer_tree)) { + return DoDrawStatus::kDiscarded; + } + if (!layer_tree || !surface_) { return DoDrawStatus::kFailed; } @@ -420,8 +427,6 @@ Rasterizer::DoDrawStatus Rasterizer::DoDraw( return DoDrawStatus::kRetry; } else if (draw_surface_status == DrawSurfaceStatus::kGpuUnavailable) { return DoDrawStatus::kGpuUnavailable; - } else if (draw_surface_status == DrawSurfaceStatus::kDiscarded) { - return DoDrawStatus::kDiscarded; } FML_DCHECK(draw_surface_status == DrawSurfaceStatus::kSuccess || draw_surface_status == DrawSurfaceStatus::kFailed); @@ -513,13 +518,6 @@ Rasterizer::DrawSurfaceStatus Rasterizer::DrawToSurface( TRACE_EVENT0("flutter", "Rasterizer::DrawToSurface"); FML_DCHECK(surface_); - // TODO(dkwingsmt): Use a proper view ID when Rasterizer supports - // multi-view. - int64_t view_id = kFlutterImplicitViewId; - if (delegate_.ShouldDiscardLayerTree(view_id, layer_tree)) { - return DrawSurfaceStatus::kDiscarded; - } - DrawSurfaceStatus draw_surface_status; if (surface_->AllowsDrawingWhenGpuDisabled()) { draw_surface_status = DrawToSurfaceUnsafe(frame_timings_recorder, diff --git a/shell/common/rasterizer.h b/shell/common/rasterizer.h index e38f4ba7aa773..ca33e8444e12b 100644 --- a/shell/common/rasterizer.h +++ b/shell/common/rasterizer.h @@ -545,8 +545,6 @@ class Rasterizer final : public SnapshotDelegate, kRetry, // Failed to rasterize the frame. kFailed, - // Layer tree was discarded due to LayerTreeDiscardCallback. - kDiscarded, // Layer tree was discarded due to inability to access the GPU. kGpuUnavailable, }; From 9b3c12f728fa661383af1d1949da204f20981fd2 Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Sun, 3 Sep 2023 22:36:25 -0700 Subject: [PATCH 14/48] Revert some changes --- shell/common/rasterizer.cc | 87 ++++++++++++++++++++------------------ shell/common/rasterizer.h | 13 +++--- 2 files changed, 52 insertions(+), 48 deletions(-) diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index 82053fe1f630c..d894b1a8c9120 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -182,13 +182,12 @@ void Rasterizer::DrawLastLayerTree( if (!last_layer_tree_ || !surface_) { return; } - DrawSurfaceStatus draw_surface_status = DrawToSurface( + DoDrawStatus status = DrawToSurface( *frame_timings_recorder, *last_layer_tree_, last_device_pixel_ratio_); // EndFrame should perform cleanups for the external_view_embedder. if (external_view_embedder_ && external_view_embedder_->GetUsedThisFrame()) { - bool should_resubmit_frame = - draw_surface_status == DrawSurfaceStatus::kRetry; + bool should_resubmit_frame = status == DoDrawStatus::kRetry; external_view_embedder_->SetUsedThisFrame(false); external_view_embedder_->EndFrame(should_resubmit_frame, raster_thread_merger_); @@ -209,21 +208,23 @@ DrawStatus Rasterizer::Draw( DoDrawResult draw_result; LayerTreePipeline::Consumer consumer = - [&draw_result, this](std::unique_ptr item) { - std::unique_ptr layer_tree = std::move(item->layer_tree); - std::unique_ptr frame_timings_recorder = - std::move(item->frame_timings_recorder); + [&draw_result, this, + &delegate = delegate_](std::unique_ptr item) { // TODO(dkwingsmt): Use a proper view ID when Rasterizer supports // multi-view. int64_t view_id = kFlutterImplicitViewId; - if (delegate_.ShouldDiscardLayerTree(view_id, *layer_tree)) { + std::unique_ptr layer_tree = std::move(item->layer_tree); + std::unique_ptr frame_timings_recorder = + std::move(item->frame_timings_recorder); + float device_pixel_ratio = item->device_pixel_ratio; + if (delegate.ShouldDiscardLayerTree(view_id, *layer_tree)) { draw_result = DoDrawResult{ .raster_status = DoDrawStatus::kDiscarded, }; + } else { + draw_result = DoDraw(std::move(frame_timings_recorder), + std::move(layer_tree), device_pixel_ratio); } - float device_pixel_ratio = item->device_pixel_ratio; - draw_result = DoDraw(std::move(frame_timings_recorder), - std::move(layer_tree), device_pixel_ratio); }; PipelineConsumeResult consume_result = pipeline->Consume(consumer); @@ -272,8 +273,8 @@ DrawStatus Rasterizer::Draw( return ToDrawStatus(draw_result.raster_status); } -DrawStatus Rasterizer::ToDrawStatus(DoDrawStatus do_draw_status) { - switch (do_draw_status) { +DrawStatus Rasterizer::ToDrawStatus(DoDrawStatus status) { + switch (status) { case DoDrawStatus::kGpuUnavailable: return DrawStatus::kGpuUnavailable; case DoDrawStatus::kDiscarded: @@ -418,9 +419,12 @@ Rasterizer::DoDrawResult Rasterizer::DoDraw( PersistentCache* persistent_cache = PersistentCache::GetCacheForProcess(); persistent_cache->ResetStoredNewShaders(); - DrawSurfaceStatus draw_surface_status = + DoDrawStatus status = DrawToSurface(*frame_timings_recorder, *layer_tree, device_pixel_ratio); - if (draw_surface_status == DrawSurfaceStatus::kRetry) { + if (status == DoDrawStatus::kSuccess) { + last_layer_tree_ = std::move(layer_tree); + last_device_pixel_ratio_ = device_pixel_ratio; + } else if (status == DoDrawStatus::kRetry) { return DoDrawResult{ .raster_status = DoDrawStatus::kRetry, .resubmitted_layer_tree_item = std::make_unique( @@ -429,17 +433,13 @@ Rasterizer::DoDrawResult Rasterizer::DoDraw( FrameTimingsRecorder::State::kBuildEnd), device_pixel_ratio), }; - } else if (draw_surface_status == DrawSurfaceStatus::kGpuUnavailable) { + } else if (status == DoDrawStatus::kGpuUnavailable) { return DoDrawResult{ .raster_status = DoDrawStatus::kGpuUnavailable, }; } - FML_DCHECK(draw_surface_status == DrawSurfaceStatus::kSuccess || - draw_surface_status == DrawSurfaceStatus::kFailed); - if (draw_surface_status == DrawSurfaceStatus::kSuccess) { - last_layer_tree_ = std::move(layer_tree); - last_device_pixel_ratio_ = device_pixel_ratio; - } + FML_DCHECK(status == DoDrawStatus::kSuccess || + status == DoDrawStatus::kFailed); if (persistent_cache->IsDumpingSkp() && persistent_cache->StoredNewShaders()) { @@ -512,41 +512,46 @@ Rasterizer::DoDrawResult Rasterizer::DoDraw( } } - if (draw_surface_status == DrawSurfaceStatus::kSuccess) { - return DoDrawResult{ - .raster_status = DoDrawStatus::kSuccess, - }; - } else { - return DoDrawResult{ - .raster_status = DoDrawStatus::kFailed, - }; - } + return DoDrawResult{ + .raster_status = status, + }; } -Rasterizer::DrawSurfaceStatus Rasterizer::DrawToSurface( +Rasterizer::DoDrawStatus Rasterizer::DrawToSurface( FrameTimingsRecorder& frame_timings_recorder, flutter::LayerTree& layer_tree, float device_pixel_ratio) { TRACE_EVENT0("flutter", "Rasterizer::DrawToSurface"); FML_DCHECK(surface_); - DrawSurfaceStatus draw_surface_status; + DoDrawStatus status; if (surface_->AllowsDrawingWhenGpuDisabled()) { - draw_surface_status = DrawToSurfaceUnsafe(frame_timings_recorder, - layer_tree, device_pixel_ratio); + status = ToDoDrawStatus(DrawToSurfaceUnsafe( + frame_timings_recorder, layer_tree, device_pixel_ratio)); } else { delegate_.GetIsGpuDisabledSyncSwitch()->Execute( fml::SyncSwitch::Handlers() - .SetIfTrue([&] { - draw_surface_status = DrawSurfaceStatus::kGpuUnavailable; - }) + .SetIfTrue([&] { status = DoDrawStatus::kGpuUnavailable; }) .SetIfFalse([&] { - draw_surface_status = DrawToSurfaceUnsafe( - frame_timings_recorder, layer_tree, device_pixel_ratio); + status = ToDoDrawStatus(DrawToSurfaceUnsafe( + frame_timings_recorder, layer_tree, device_pixel_ratio)); })); } - return draw_surface_status; + return status; +} + +Rasterizer::DoDrawStatus Rasterizer::ToDoDrawStatus(DrawSurfaceStatus status) { + switch (status) { + case DrawSurfaceStatus::kRetry: + return DoDrawStatus::kRetry; + case DrawSurfaceStatus::kFailed: + return DoDrawStatus::kFailed; + case DrawSurfaceStatus::kSuccess: + return DoDrawStatus::kSuccess; + default: + FML_CHECK(false); + } } /// Unsafe because it assumes we have access to the GPU which isn't the case diff --git a/shell/common/rasterizer.h b/shell/common/rasterizer.h index f7c155fc92d22..8f01984fa19f7 100644 --- a/shell/common/rasterizer.h +++ b/shell/common/rasterizer.h @@ -529,7 +529,7 @@ class Rasterizer final : public SnapshotDelegate, void DisableThreadMergerIfNeeded(); private: - // The result status of DrawToSurface and DrawToSurfaceUnsafe. + // The result status of DrawToSurfaceUnsafe. enum class DrawSurfaceStatus { // Frame has been successfully rasterized. kSuccess, @@ -545,8 +545,6 @@ class Rasterizer final : public SnapshotDelegate, kRetry, // Failed to rasterize the frame. kFailed, - // Layer tree was discarded due to inability to access the GPU. - kGpuUnavailable, }; // The result status of DoDraw. @@ -648,9 +646,9 @@ class Rasterizer final : public SnapshotDelegate, std::unique_ptr layer_tree, float device_pixel_ratio); - DrawSurfaceStatus DrawToSurface(FrameTimingsRecorder& frame_timings_recorder, - flutter::LayerTree& layer_tree, - float device_pixel_ratio); + DoDrawStatus DrawToSurface(FrameTimingsRecorder& frame_timings_recorder, + flutter::LayerTree& layer_tree, + float device_pixel_ratio); DrawSurfaceStatus DrawToSurfaceUnsafe( FrameTimingsRecorder& frame_timings_recorder, @@ -659,7 +657,8 @@ class Rasterizer final : public SnapshotDelegate, void FireNextFrameCallbackIfPresent(); - static DrawStatus ToDrawStatus(DoDrawStatus do_draw_status); + static DoDrawStatus ToDoDrawStatus(DrawSurfaceStatus status); + static DrawStatus ToDrawStatus(DoDrawStatus status); Delegate& delegate_; MakeGpuImageBehavior gpu_image_behavior_; From 69ea3671db4b7bf98776615a943816039ec9dea9 Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Sun, 3 Sep 2023 22:45:36 -0700 Subject: [PATCH 15/48] Revert more changes --- shell/common/rasterizer.cc | 11 +++++------ shell/common/rasterizer.h | 2 +- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index d894b1a8c9120..ec07358194e5d 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -218,9 +218,7 @@ DrawStatus Rasterizer::Draw( std::move(item->frame_timings_recorder); float device_pixel_ratio = item->device_pixel_ratio; if (delegate.ShouldDiscardLayerTree(view_id, *layer_tree)) { - draw_result = DoDrawResult{ - .raster_status = DoDrawStatus::kDiscarded, - }; + draw_result.raster_status = DoDrawStatus::kDiscarded; } else { draw_result = DoDraw(std::move(frame_timings_recorder), std::move(layer_tree), device_pixel_ratio); @@ -282,6 +280,7 @@ DrawStatus Rasterizer::ToDrawStatus(DoDrawStatus status) { case DoDrawStatus::kFailed: return DrawStatus::kFailed; default: + FML_CHECK(status == DoDrawStatus::kSuccess); return DrawStatus::kSuccess; } } @@ -547,10 +546,9 @@ Rasterizer::DoDrawStatus Rasterizer::ToDoDrawStatus(DrawSurfaceStatus status) { return DoDrawStatus::kRetry; case DrawSurfaceStatus::kFailed: return DoDrawStatus::kFailed; - case DrawSurfaceStatus::kSuccess: - return DoDrawStatus::kSuccess; default: - FML_CHECK(false); + FML_CHECK(status == DrawSurfaceStatus::kSuccess); + return DoDrawStatus::kSuccess; } } @@ -692,6 +690,7 @@ Rasterizer::DrawSurfaceStatus Rasterizer::DrawToSurfaceUnsafe( if (frame_status == RasterStatus::kResubmit) { return DrawSurfaceStatus::kRetry; } else { + FML_CHECK(frame_status == RasterStatus::kSuccess); return DrawSurfaceStatus::kSuccess; } } diff --git a/shell/common/rasterizer.h b/shell/common/rasterizer.h index 8f01984fa19f7..0d2b9b97586ab 100644 --- a/shell/common/rasterizer.h +++ b/shell/common/rasterizer.h @@ -48,7 +48,7 @@ class AiksContext; namespace flutter { -// The result status of Rasterizer::DoDraw. This is only used for unit tests. +// The result status of Rasterizer::Draw. This is only used for unit tests. enum class DrawStatus { // Frame has been successfully rasterized. kSuccess, From f2cd6e3f69351e1a58376fd584d556a634c1c1ae Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Sun, 3 Sep 2023 23:29:20 -0700 Subject: [PATCH 16/48] Rename to status --- shell/common/rasterizer.cc | 18 +++++++++--------- shell/common/rasterizer.h | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index ec07358194e5d..15905c18c79bd 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -218,7 +218,7 @@ DrawStatus Rasterizer::Draw( std::move(item->frame_timings_recorder); float device_pixel_ratio = item->device_pixel_ratio; if (delegate.ShouldDiscardLayerTree(view_id, *layer_tree)) { - draw_result.raster_status = DoDrawStatus::kDiscarded; + draw_result.status = DoDrawStatus::kDiscarded; } else { draw_result = DoDraw(std::move(frame_timings_recorder), std::move(layer_tree), device_pixel_ratio); @@ -233,7 +233,7 @@ DrawStatus Rasterizer::Draw( // front of the queue and also change the consume status to more available. bool should_resubmit_frame = - draw_result.raster_status == DoDrawStatus::kRetry; + draw_result.status == DoDrawStatus::kRetry; if (should_resubmit_frame) { auto front_continuation = pipeline->ProduceIfEmpty(); PipelineProduceResult pipeline_result = front_continuation.Complete( @@ -241,7 +241,7 @@ DrawStatus Rasterizer::Draw( if (pipeline_result.success) { consume_result = PipelineConsumeResult::MoreAvailable; } - } else if (draw_result.raster_status == DoDrawStatus::kEnqueuePipeline) { + } else if (draw_result.status == DoDrawStatus::kEnqueuePipeline) { consume_result = PipelineConsumeResult::MoreAvailable; } @@ -268,7 +268,7 @@ DrawStatus Rasterizer::Draw( break; } - return ToDrawStatus(draw_result.raster_status); + return ToDrawStatus(draw_result.status); } DrawStatus Rasterizer::ToDrawStatus(DoDrawStatus status) { @@ -411,7 +411,7 @@ Rasterizer::DoDrawResult Rasterizer::DoDraw( if (!layer_tree || !surface_) { return DoDrawResult{ - .raster_status = DoDrawStatus::kFailed, + .status = DoDrawStatus::kFailed, }; } @@ -425,7 +425,7 @@ Rasterizer::DoDrawResult Rasterizer::DoDraw( last_device_pixel_ratio_ = device_pixel_ratio; } else if (status == DoDrawStatus::kRetry) { return DoDrawResult{ - .raster_status = DoDrawStatus::kRetry, + .status = DoDrawStatus::kRetry, .resubmitted_layer_tree_item = std::make_unique( std::move(layer_tree), frame_timings_recorder->CloneUntil( @@ -434,7 +434,7 @@ Rasterizer::DoDrawResult Rasterizer::DoDraw( }; } else if (status == DoDrawStatus::kGpuUnavailable) { return DoDrawResult{ - .raster_status = DoDrawStatus::kGpuUnavailable, + .status = DoDrawStatus::kGpuUnavailable, }; } FML_DCHECK(status == DoDrawStatus::kSuccess || @@ -506,13 +506,13 @@ Rasterizer::DoDrawResult Rasterizer::DoDraw( if (raster_thread_merger_->DecrementLease() == fml::RasterThreadStatus::kUnmergedNow) { return DoDrawResult{ - .raster_status = DoDrawStatus::kEnqueuePipeline, + .status = DoDrawStatus::kEnqueuePipeline, }; } } return DoDrawResult{ - .raster_status = status, + .status = status, }; } diff --git a/shell/common/rasterizer.h b/shell/common/rasterizer.h index 0d2b9b97586ab..5c2809faa2f9a 100644 --- a/shell/common/rasterizer.h +++ b/shell/common/rasterizer.h @@ -547,7 +547,7 @@ class Rasterizer final : public SnapshotDelegate, kFailed, }; - // The result status of DoDraw. + // The result status of DoDraw and DrawToSurface. enum class DoDrawStatus { // Frame has been successfully rasterized. kSuccess, @@ -581,7 +581,7 @@ class Rasterizer final : public SnapshotDelegate, // configuration, in which case the resubmitted task will be inserted to the // front of the pipeline. struct DoDrawResult { - DoDrawStatus raster_status = DoDrawStatus::kSuccess; + DoDrawStatus status = DoDrawStatus::kSuccess; std::unique_ptr resubmitted_layer_tree_item; }; From d0d66ef079c63bd9067635cddbe7fa5b23ef2109 Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Mon, 4 Sep 2023 10:21:52 -0700 Subject: [PATCH 17/48] lint --- shell/common/rasterizer.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index 15905c18c79bd..06ff4c94c793f 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -232,8 +232,7 @@ DrawStatus Rasterizer::Draw( // if the raster status is to resubmit the frame, we push the frame to the // front of the queue and also change the consume status to more available. - bool should_resubmit_frame = - draw_result.status == DoDrawStatus::kRetry; + bool should_resubmit_frame = draw_result.status == DoDrawStatus::kRetry; if (should_resubmit_frame) { auto front_continuation = pipeline->ProduceIfEmpty(); PipelineProduceResult pipeline_result = front_continuation.Complete( From 3d94b8e0228252969a80d2173b372f0914645b48 Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Tue, 5 Sep 2023 14:54:08 -0700 Subject: [PATCH 18/48] Convert to LayerTreeTask --- flow/layers/layer_tree.h | 12 +++ shell/common/animator.cc | 13 ++-- shell/common/animator.h | 1 - shell/common/pipeline.h | 17 ++--- shell/common/rasterizer.cc | 35 +++++---- shell/common/rasterizer.h | 2 +- shell/common/rasterizer_unittests.cc | 106 +++++++++++++++++---------- 7 files changed, 116 insertions(+), 70 deletions(-) diff --git a/flow/layers/layer_tree.h b/flow/layers/layer_tree.h index 5f573da2099a0..6c374ecf3a228 100644 --- a/flow/layers/layer_tree.h +++ b/flow/layers/layer_tree.h @@ -94,6 +94,18 @@ class LayerTree { FML_DISALLOW_COPY_AND_ASSIGN(LayerTree); }; +struct LayerTreeTask { + LayerTreeTask(int64_t view_id, + std::unique_ptr layer_tree, + float device_pixel_ratio) + : view_id(view_id), + layer_tree(std::move(layer_tree)), + device_pixel_ratio(device_pixel_ratio) {} + int64_t view_id; + std::unique_ptr layer_tree; + float device_pixel_ratio; +}; + } // namespace flutter #endif // FLUTTER_FLOW_LAYERS_LAYER_TREE_H_ diff --git a/shell/common/animator.cc b/shell/common/animator.cc index 29c21c1ae5592..967ec6b39b631 100644 --- a/shell/common/animator.cc +++ b/shell/common/animator.cc @@ -4,6 +4,7 @@ #include "flutter/shell/common/animator.h" +#include "flutter/common/constants.h" #include "flutter/flow/frame_timings.h" #include "flutter/fml/time/time_point.h" #include "flutter/fml/trace_event.h" @@ -140,7 +141,6 @@ void Animator::BeginFrame( void Animator::Render(std::unique_ptr layer_tree, float device_pixel_ratio) { has_rendered_ = true; - last_layer_tree_size_ = layer_tree->frame_size(); if (!frame_timings_recorder_) { // Framework can directly call render with a built scene. @@ -158,12 +158,15 @@ void Animator::Render(std::unique_ptr layer_tree, delegate_.OnAnimatorUpdateLatestFrameTargetTime( frame_timings_recorder_->GetVsyncTargetTime()); - auto layer_tree_item = std::make_unique( - std::move(layer_tree), std::move(frame_timings_recorder_), - device_pixel_ratio); + // TODO(dkwingsmt): Currently only supports a single window. + int64_t view_id = kFlutterImplicitViewId; + std::list layer_trees_tasks; + layer_trees_tasks.emplace_back(view_id, std::move(layer_tree), + device_pixel_ratio); // Commit the pending continuation. PipelineProduceResult result = - producer_continuation_.Complete(std::move(layer_tree_item)); + producer_continuation_.Complete(std::make_unique( + std::move(layer_trees_tasks), std::move(frame_timings_recorder_))); if (!result.success) { FML_DLOG(INFO) << "No pending continuation to commit"; diff --git a/shell/common/animator.h b/shell/common/animator.h index 4e6295957bdcc..28a3430932a5e 100644 --- a/shell/common/animator.h +++ b/shell/common/animator.h @@ -107,7 +107,6 @@ class Animator final { LayerTreePipeline::ProducerContinuation producer_continuation_; bool regenerate_layer_tree_ = false; bool frame_scheduled_ = false; - SkISize last_layer_tree_size_ = {0, 0}; std::deque trace_flow_ids_; bool has_rendered_ = false; diff --git a/shell/common/pipeline.h b/shell/common/pipeline.h index c76ccbedbcd49..b03994e61bd69 100644 --- a/shell/common/pipeline.h +++ b/shell/common/pipeline.h @@ -253,19 +253,16 @@ class Pipeline { FML_DISALLOW_COPY_AND_ASSIGN(Pipeline); }; -struct LayerTreeItem { - LayerTreeItem(std::unique_ptr layer_tree, - std::unique_ptr frame_timings_recorder, - float device_pixel_ratio) - : layer_tree(std::move(layer_tree)), - frame_timings_recorder(std::move(frame_timings_recorder)), - device_pixel_ratio(device_pixel_ratio) {} - std::unique_ptr layer_tree; +struct FrameItem { + FrameItem(std::list tasks, + std::unique_ptr frame_timings_recorder) + : tasks(std::move(tasks)), + frame_timings_recorder(std::move(frame_timings_recorder)) {} + std::list tasks; std::unique_ptr frame_timings_recorder; - float device_pixel_ratio; }; -using LayerTreePipeline = Pipeline; +using LayerTreePipeline = Pipeline; } // namespace flutter diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index 06ff4c94c793f..1970ac8673c5b 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -209,15 +209,21 @@ DrawStatus Rasterizer::Draw( DoDrawResult draw_result; LayerTreePipeline::Consumer consumer = [&draw_result, this, - &delegate = delegate_](std::unique_ptr item) { - // TODO(dkwingsmt): Use a proper view ID when Rasterizer supports - // multi-view. - int64_t view_id = kFlutterImplicitViewId; - std::unique_ptr layer_tree = std::move(item->layer_tree); + &delegate = delegate_](std::unique_ptr item) { + // TODO(dkwingsmt): The rasterizer only supports rendering a single view + // and that view must be the implicit view. Properly support multi-view + // in the future. + FML_DCHECK(item->tasks.size() <= 1u); + if (item->tasks.empty()) { + return; + } + auto& task = item->tasks.front(); + FML_DCHECK(task.view_id == kFlutterImplicitViewId); + std::unique_ptr layer_tree = std::move(task.layer_tree); std::unique_ptr frame_timings_recorder = std::move(item->frame_timings_recorder); - float device_pixel_ratio = item->device_pixel_ratio; - if (delegate.ShouldDiscardLayerTree(view_id, *layer_tree)) { + float device_pixel_ratio = task.device_pixel_ratio; + if (delegate.ShouldDiscardLayerTree(task.view_id, *layer_tree)) { draw_result.status = DoDrawStatus::kDiscarded; } else { draw_result = DoDraw(std::move(frame_timings_recorder), @@ -234,9 +240,10 @@ DrawStatus Rasterizer::Draw( bool should_resubmit_frame = draw_result.status == DoDrawStatus::kRetry; if (should_resubmit_frame) { + FML_CHECK(draw_result.resubmitted_item); auto front_continuation = pipeline->ProduceIfEmpty(); - PipelineProduceResult pipeline_result = front_continuation.Complete( - std::move(draw_result.resubmitted_layer_tree_item)); + PipelineProduceResult pipeline_result = + front_continuation.Complete(std::move(draw_result.resubmitted_item)); if (pipeline_result.success) { consume_result = PipelineConsumeResult::MoreAvailable; } @@ -423,13 +430,15 @@ Rasterizer::DoDrawResult Rasterizer::DoDraw( last_layer_tree_ = std::move(layer_tree); last_device_pixel_ratio_ = device_pixel_ratio; } else if (status == DoDrawStatus::kRetry) { + std::list resubmitted_tasks; + resubmitted_tasks.emplace_back(kFlutterImplicitViewId, + std::move(layer_tree), device_pixel_ratio); return DoDrawResult{ .status = DoDrawStatus::kRetry, - .resubmitted_layer_tree_item = std::make_unique( - std::move(layer_tree), + .resubmitted_item = std::make_unique( + std::move(resubmitted_tasks), frame_timings_recorder->CloneUntil( - FrameTimingsRecorder::State::kBuildEnd), - device_pixel_ratio), + FrameTimingsRecorder::State::kBuildEnd)), }; } else if (status == DoDrawStatus::kGpuUnavailable) { return DoDrawResult{ diff --git a/shell/common/rasterizer.h b/shell/common/rasterizer.h index 5c2809faa2f9a..700e4a6ecf0ce 100644 --- a/shell/common/rasterizer.h +++ b/shell/common/rasterizer.h @@ -583,7 +583,7 @@ class Rasterizer final : public SnapshotDelegate, struct DoDrawResult { DoDrawStatus status = DoDrawStatus::kSuccess; - std::unique_ptr resubmitted_layer_tree_item; + std::unique_ptr resubmitted_item; }; // |SnapshotDelegate| diff --git a/shell/common/rasterizer_unittests.cc b/shell/common/rasterizer_unittests.cc index f6033681cb92c..4d791a560f048 100644 --- a/shell/common/rasterizer_unittests.cc +++ b/shell/common/rasterizer_unittests.cc @@ -31,6 +31,16 @@ namespace flutter { namespace { constexpr float kDevicePixelRatio = 2.0f; +constexpr int64_t kImplicitViewId = 0; + +std::list SingleLayerTreeList( + int64_t view_id, + std::unique_ptr layer_tree, + float pixel_ratio) { + std::list tasks; + tasks.emplace_back(view_id, std::move(layer_tree), pixel_ratio); + return tasks; +} class MockDelegate : public Rasterizer::Delegate { public: @@ -217,9 +227,10 @@ TEST(RasterizerTest, auto layer_tree = std::make_unique(/*config=*/LayerTree::Config(), /*frame_size=*/SkISize()); - auto layer_tree_item = std::make_unique( - std::move(layer_tree), CreateFinishedBuildRecorder(), - kDevicePixelRatio); + auto layer_tree_item = std::make_unique( + SingleLayerTreeList(kImplicitViewId, std::move(layer_tree), + kDevicePixelRatio), + CreateFinishedBuildRecorder()); PipelineProduceResult result = pipeline->Produce().Complete(std::move(layer_tree_item)); EXPECT_TRUE(result.success); @@ -283,9 +294,10 @@ TEST( auto pipeline = std::make_shared(/*depth=*/10); auto layer_tree = std::make_unique( /*config=*/LayerTree::Config(), /*frame_size=*/SkISize()); - auto layer_tree_item = std::make_unique( - std::move(layer_tree), CreateFinishedBuildRecorder(), - kDevicePixelRatio); + auto layer_tree_item = std::make_unique( + SingleLayerTreeList(kImplicitViewId, std::move(layer_tree), + kDevicePixelRatio), + CreateFinishedBuildRecorder()); PipelineProduceResult result = pipeline->Produce().Complete(std::move(layer_tree_item)); EXPECT_TRUE(result.success); @@ -355,8 +367,10 @@ TEST( auto pipeline = std::make_shared(/*depth=*/10); auto layer_tree = std::make_unique(/*config=*/LayerTree::Config(), /*frame_size=*/SkISize()); - auto layer_tree_item = std::make_unique( - std::move(layer_tree), CreateFinishedBuildRecorder(), kDevicePixelRatio); + auto layer_tree_item = std::make_unique( + SingleLayerTreeList(kImplicitViewId, std::move(layer_tree), + kDevicePixelRatio), + CreateFinishedBuildRecorder()); PipelineProduceResult result = pipeline->Produce().Complete(std::move(layer_tree_item)); EXPECT_TRUE(result.success); @@ -429,8 +443,10 @@ TEST(RasterizerTest, auto pipeline = std::make_shared(/*depth=*/10); auto layer_tree = std::make_unique(/*config=*/LayerTree::Config(), /*frame_size=*/SkISize()); - auto layer_tree_item = std::make_unique( - std::move(layer_tree), CreateFinishedBuildRecorder(), kDevicePixelRatio); + auto layer_tree_item = std::make_unique( + SingleLayerTreeList(kImplicitViewId, std::move(layer_tree), + kDevicePixelRatio), + CreateFinishedBuildRecorder()); PipelineProduceResult result = pipeline->Produce().Complete(std::move(layer_tree_item)); EXPECT_TRUE(result.success); @@ -478,9 +494,10 @@ TEST(RasterizerTest, externalViewEmbedderDoesntEndFrameWhenNoSurfaceIsSet) { auto pipeline = std::make_shared(/*depth=*/10); auto layer_tree = std::make_unique( /*config=*/LayerTree::Config(), /*frame_size=*/SkISize()); - auto layer_tree_item = std::make_unique( - std::move(layer_tree), CreateFinishedBuildRecorder(), - kDevicePixelRatio); + auto layer_tree_item = std::make_unique( + SingleLayerTreeList(kImplicitViewId, std::move(layer_tree), + kDevicePixelRatio), + CreateFinishedBuildRecorder()); PipelineProduceResult result = pipeline->Produce().Complete(std::move(layer_tree_item)); EXPECT_TRUE(result.success); @@ -534,9 +551,10 @@ TEST(RasterizerTest, externalViewEmbedderDoesntEndFrameWhenNotUsedThisFrame) { auto pipeline = std::make_shared(/*depth=*/10); auto layer_tree = std::make_unique( /*config=*/LayerTree::Config(), /*frame_size=*/SkISize()); - auto layer_tree_item = std::make_unique( - std::move(layer_tree), CreateFinishedBuildRecorder(), - kDevicePixelRatio); + auto layer_tree_item = std::make_unique( + SingleLayerTreeList(kImplicitViewId, std::move(layer_tree), + kDevicePixelRatio), + CreateFinishedBuildRecorder()); PipelineProduceResult result = pipeline->Produce().Complete(std::move(layer_tree_item)); EXPECT_TRUE(result.success); @@ -637,9 +655,10 @@ TEST(RasterizerTest, auto pipeline = std::make_shared(/*depth=*/10); auto layer_tree = std::make_unique( /*config=*/LayerTree::Config(), /*frame_size=*/SkISize()); - auto layer_tree_item = std::make_unique( - std::move(layer_tree), CreateFinishedBuildRecorder(), - kDevicePixelRatio); + auto layer_tree_item = std::make_unique( + SingleLayerTreeList(kImplicitViewId, std::move(layer_tree), + kDevicePixelRatio), + CreateFinishedBuildRecorder()); PipelineProduceResult result = pipeline->Produce().Complete(std::move(layer_tree_item)); EXPECT_TRUE(result.success); @@ -695,9 +714,10 @@ TEST( auto pipeline = std::make_shared(/*depth=*/10); auto layer_tree = std::make_unique( /*config=*/LayerTree::Config(), /*frame_size=*/SkISize()); - auto layer_tree_item = std::make_unique( - std::move(layer_tree), CreateFinishedBuildRecorder(), - kDevicePixelRatio); + auto layer_tree_item = std::make_unique( + SingleLayerTreeList(kImplicitViewId, std::move(layer_tree), + kDevicePixelRatio), + CreateFinishedBuildRecorder()); PipelineProduceResult result = pipeline->Produce().Complete(std::move(layer_tree_item)); EXPECT_TRUE(result.success); @@ -753,9 +773,10 @@ TEST( auto pipeline = std::make_shared(/*depth=*/10); auto layer_tree = std::make_unique( /*config=*/LayerTree::Config(), /*frame_size=*/SkISize()); - auto layer_tree_item = std::make_unique( - std::move(layer_tree), CreateFinishedBuildRecorder(), - kDevicePixelRatio); + auto layer_tree_item = std::make_unique( + SingleLayerTreeList(kImplicitViewId, std::move(layer_tree), + kDevicePixelRatio), + CreateFinishedBuildRecorder()); PipelineProduceResult result = pipeline->Produce().Complete(std::move(layer_tree_item)); EXPECT_TRUE(result.success); @@ -810,9 +831,10 @@ TEST( auto pipeline = std::make_shared(/*depth=*/10); auto layer_tree = std::make_unique( /*config=*/LayerTree::Config(), /*frame_size=*/SkISize()); - auto layer_tree_item = std::make_unique( - std::move(layer_tree), CreateFinishedBuildRecorder(), - kDevicePixelRatio); + auto layer_tree_item = std::make_unique( + SingleLayerTreeList(kImplicitViewId, std::move(layer_tree), + kDevicePixelRatio), + CreateFinishedBuildRecorder()); PipelineProduceResult result = pipeline->Produce().Complete(std::move(layer_tree_item)); EXPECT_TRUE(result.success); @@ -866,9 +888,10 @@ TEST( auto pipeline = std::make_shared(/*depth=*/10); auto layer_tree = std::make_unique( /*config=*/LayerTree::Config(), /*frame_size=*/SkISize()); - auto layer_tree_item = std::make_unique( - std::move(layer_tree), CreateFinishedBuildRecorder(), - kDevicePixelRatio); + auto layer_tree_item = std::make_unique( + SingleLayerTreeList(kImplicitViewId, std::move(layer_tree), + kDevicePixelRatio), + CreateFinishedBuildRecorder()); PipelineProduceResult result = pipeline->Produce().Complete(std::move(layer_tree_item)); EXPECT_TRUE(result.success); @@ -945,9 +968,10 @@ TEST(RasterizerTest, for (int i = 0; i < 2; i++) { auto layer_tree = std::make_unique( /*config=*/LayerTree::Config(), /*frame_size=*/SkISize()); - auto layer_tree_item = std::make_unique( - std::move(layer_tree), CreateFinishedBuildRecorder(timestamps[i]), - kDevicePixelRatio); + auto layer_tree_item = std::make_unique( + SingleLayerTreeList(kImplicitViewId, std::move(layer_tree), + kDevicePixelRatio), + CreateFinishedBuildRecorder(timestamps[i])); PipelineProduceResult result = pipeline->Produce().Complete(std::move(layer_tree_item)); EXPECT_TRUE(result.success); @@ -1116,9 +1140,10 @@ TEST(RasterizerTest, presentationTimeSetWhenVsyncTargetInFuture) { for (int i = 0; i < 2; i++) { auto layer_tree = std::make_unique( /*config=*/LayerTree::Config(), /*frame_size=*/SkISize()); - auto layer_tree_item = std::make_unique( - std::move(layer_tree), CreateFinishedBuildRecorder(timestamps[i]), - kDevicePixelRatio); + auto layer_tree_item = std::make_unique( + SingleLayerTreeList(kImplicitViewId, std::move(layer_tree), + kDevicePixelRatio), + CreateFinishedBuildRecorder(timestamps[i])); PipelineProduceResult result = pipeline->Produce().Complete(std::move(layer_tree_item)); EXPECT_TRUE(result.success); @@ -1198,9 +1223,10 @@ TEST(RasterizerTest, presentationTimeNotSetWhenVsyncTargetInPast) { auto pipeline = std::make_shared(/*depth=*/10); auto layer_tree = std::make_unique( /*config=*/LayerTree::Config(), /*frame_size=*/SkISize()); - auto layer_tree_item = std::make_unique( - std::move(layer_tree), CreateFinishedBuildRecorder(first_timestamp), - kDevicePixelRatio); + auto layer_tree_item = std::make_unique( + SingleLayerTreeList(kImplicitViewId, std::move(layer_tree), + kDevicePixelRatio), + CreateFinishedBuildRecorder(first_timestamp)); PipelineProduceResult result = pipeline->Produce().Complete(std::move(layer_tree_item)); EXPECT_TRUE(result.success); From 9445595c93c978c53393021b2fa848a41ed44cb8 Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Tue, 5 Sep 2023 15:09:12 -0700 Subject: [PATCH 19/48] Fix retry conversion --- shell/common/rasterizer.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index 06ff4c94c793f..9b4331e529cc6 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -278,8 +278,11 @@ DrawStatus Rasterizer::ToDrawStatus(DoDrawStatus status) { return DrawStatus::kDiscarded; case DoDrawStatus::kFailed: return DrawStatus::kFailed; + case DoDrawStatus::kRetry: + return DrawStatus::kSuccess; default: - FML_CHECK(status == DoDrawStatus::kSuccess); + FML_CHECK(status == DoDrawStatus::kSuccess) + << "Unrecognized status " << (int)status; return DrawStatus::kSuccess; } } From 174f6d7a5e20e463d4c5578db573e428d3815f1f Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Wed, 6 Sep 2023 22:41:22 -0700 Subject: [PATCH 20/48] Multiview DoDraw and DrawToSurface --- shell/common/rasterizer.cc | 190 +++++++++++++++++++------------- shell/common/rasterizer.h | 37 +++---- shell/common/shell.cc | 5 +- shell/common/shell_unittests.cc | 18 ++- 4 files changed, 140 insertions(+), 110 deletions(-) diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index b646daf84644d..9233df0a899fe 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -39,7 +39,8 @@ static constexpr std::chrono::milliseconds kSkiaCleanupExpiration(15000); Rasterizer::Rasterizer(Delegate& delegate, MakeGpuImageBehavior gpu_image_behavior) - : delegate_(delegate), + : is_torn_down_(false), + delegate_(delegate), gpu_image_behavior_(gpu_image_behavior), compositor_context_(std::make_unique(*this)), user_override_resource_cache_bytes_(false), @@ -105,6 +106,7 @@ void Rasterizer::TeardownExternalViewEmbedder() { } void Rasterizer::Teardown() { + is_torn_down_ = true; if (surface_) { auto context_switch = surface_->MakeRenderContextCurrent(); if (context_switch->GetResult()) { @@ -116,7 +118,7 @@ void Rasterizer::Teardown() { surface_.reset(); } - last_layer_tree_.reset(); + last_successful_tasks_.clear(); if (raster_thread_merger_.get() != nullptr && raster_thread_merger_.get()->IsMerged()) { @@ -126,6 +128,10 @@ void Rasterizer::Teardown() { } } +bool Rasterizer::IsTornDown() { + return is_torn_down_; +} + void Rasterizer::EnableThreadMergerIfNeeded() { if (raster_thread_merger_) { raster_thread_merger_->Enable(); @@ -158,11 +164,7 @@ void Rasterizer::NotifyLowMemoryWarning() const { } void Rasterizer::CollectView(int64_t view_id) { - // TODO(dkwingsmt): When Rasterizer supports multi-view, this method should - // correctly clear the view corresponding to the ID. - if (view_id == kFlutterImplicitViewId) { - last_layer_tree_.reset(); - } + last_successful_tasks_.erase(view_id); } std::shared_ptr Rasterizer::GetTextureRegistry() { @@ -173,21 +175,31 @@ GrDirectContext* Rasterizer::GetGrContext() { return surface_ ? surface_->GetContext() : nullptr; } -flutter::LayerTree* Rasterizer::GetLastLayerTree() { - return last_layer_tree_.get(); +flutter::LayerTree* Rasterizer::GetLastLayerTree(int64_t view_id) { + auto found = last_successful_tasks_.find(view_id); + if (found == last_successful_tasks_.end()) { + return nullptr; + } + return found->second.layer_tree.get(); } void Rasterizer::DrawLastLayerTree( std::unique_ptr frame_timings_recorder) { - if (!last_layer_tree_ || !surface_) { + if (last_successful_tasks_.empty() || !surface_) { return; } - DoDrawStatus status = DrawToSurface( - *frame_timings_recorder, *last_layer_tree_, last_device_pixel_ratio_); + std::list tasks; + for (auto& [view_id, task] : last_successful_tasks_) { + tasks.push_back(std::move(task)); + } + last_successful_tasks_.clear(); + + DoDrawResult result = + DrawToSurface(*frame_timings_recorder, std::move(tasks)); // EndFrame should perform cleanups for the external_view_embedder. if (external_view_embedder_ && external_view_embedder_->GetUsedThisFrame()) { - bool should_resubmit_frame = status == DoDrawStatus::kRetry; + bool should_resubmit_frame = ShouldResubmitFrame(result); external_view_embedder_->SetUsedThisFrame(false); external_view_embedder_->EndFrame(should_resubmit_frame, raster_thread_merger_); @@ -207,29 +219,15 @@ DrawStatus Rasterizer::Draw( ->RunsTasksOnCurrentThread()); DoDrawResult draw_result; - LayerTreePipeline::Consumer consumer = - [&draw_result, this, - &delegate = delegate_](std::unique_ptr item) { - // TODO(dkwingsmt): The rasterizer only supports rendering a single view - // and that view must be the implicit view. Properly support multi-view - // in the future. - FML_DCHECK(item->tasks.size() <= 1u); - if (item->tasks.empty()) { - return; - } - auto& task = item->tasks.front(); - FML_DCHECK(task.view_id == kFlutterImplicitViewId); - std::unique_ptr layer_tree = std::move(task.layer_tree); - std::unique_ptr frame_timings_recorder = - std::move(item->frame_timings_recorder); - float device_pixel_ratio = task.device_pixel_ratio; - if (delegate.ShouldDiscardLayerTree(task.view_id, *layer_tree)) { - draw_result.status = DoDrawStatus::kDiscarded; - } else { - draw_result = DoDraw(std::move(frame_timings_recorder), - std::move(layer_tree), device_pixel_ratio); - } - }; + LayerTreePipeline::Consumer consumer = [&draw_result, this]( + std::unique_ptr item) { + if (item->tasks.empty()) { + draw_result.status = DoDrawStatus::kSuccess; + return; + } + draw_result = + DoDraw(std::move(item->frame_timings_recorder), std::move(item->tasks)); + }; PipelineConsumeResult consume_result = pipeline->Consume(consumer); if (consume_result == PipelineConsumeResult::NoneAvailable) { @@ -238,9 +236,8 @@ DrawStatus Rasterizer::Draw( // if the raster status is to resubmit the frame, we push the frame to the // front of the queue and also change the consume status to more available. - bool should_resubmit_frame = draw_result.status == DoDrawStatus::kRetry; + bool should_resubmit_frame = ShouldResubmitFrame(draw_result); if (should_resubmit_frame) { - FML_CHECK(draw_result.resubmitted_item); auto front_continuation = pipeline->ProduceIfEmpty(); PipelineProduceResult pipeline_result = front_continuation.Complete(std::move(draw_result.resubmitted_item)); @@ -277,6 +274,14 @@ DrawStatus Rasterizer::Draw( return ToDrawStatus(draw_result.status); } +bool Rasterizer::ShouldResubmitFrame(const DoDrawResult& result) { + if (result.resubmitted_item) { + FML_CHECK(!result.resubmitted_item->tasks.empty()); + return true; + } + return false; +} + DrawStatus Rasterizer::ToDrawStatus(DoDrawStatus status) { switch (status) { case DoDrawStatus::kGpuUnavailable: @@ -285,8 +290,6 @@ DrawStatus Rasterizer::ToDrawStatus(DoDrawStatus status) { return DrawStatus::kDiscarded; case DoDrawStatus::kFailed: return DrawStatus::kFailed; - case DoDrawStatus::kRetry: - return DrawStatus::kSuccess; default: FML_CHECK(status == DoDrawStatus::kSuccess) << "Unrecognized status " << (int)status; @@ -409,8 +412,7 @@ fml::Milliseconds Rasterizer::GetFrameBudget() const { Rasterizer::DoDrawResult Rasterizer::DoDraw( std::unique_ptr frame_timings_recorder, - std::unique_ptr layer_tree, - float device_pixel_ratio) { + std::list tasks) { TRACE_EVENT_WITH_FRAME_NUMBER(frame_timings_recorder, "flutter", "Rasterizer::DoDraw", /*flow_id_count=*/0, /*flow_ids=*/nullptr); @@ -418,7 +420,7 @@ Rasterizer::DoDrawResult Rasterizer::DoDraw( .GetRasterTaskRunner() ->RunsTasksOnCurrentThread()); - if (!layer_tree || !surface_) { + if (!surface_) { return DoDrawResult{ .status = DoDrawStatus::kFailed, }; @@ -427,29 +429,14 @@ Rasterizer::DoDrawResult Rasterizer::DoDraw( PersistentCache* persistent_cache = PersistentCache::GetCacheForProcess(); persistent_cache->ResetStoredNewShaders(); - DoDrawStatus status = - DrawToSurface(*frame_timings_recorder, *layer_tree, device_pixel_ratio); - if (status == DoDrawStatus::kSuccess) { - last_layer_tree_ = std::move(layer_tree); - last_device_pixel_ratio_ = device_pixel_ratio; - } else if (status == DoDrawStatus::kRetry) { - std::list resubmitted_tasks; - resubmitted_tasks.emplace_back(kFlutterImplicitViewId, - std::move(layer_tree), device_pixel_ratio); - return DoDrawResult{ - .status = DoDrawStatus::kRetry, - .resubmitted_item = std::make_unique( - std::move(resubmitted_tasks), - frame_timings_recorder->CloneUntil( - FrameTimingsRecorder::State::kBuildEnd)), - }; - } else if (status == DoDrawStatus::kGpuUnavailable) { + DoDrawResult result = + DrawToSurface(*frame_timings_recorder, std::move(tasks)); + FML_DCHECK(result.status != DoDrawStatus::kEnqueuePipeline); + if (result.status == DoDrawStatus::kGpuUnavailable) { return DoDrawResult{ .status = DoDrawStatus::kGpuUnavailable, }; } - FML_DCHECK(status == DoDrawStatus::kSuccess || - status == DoDrawStatus::kFailed); if (persistent_cache->IsDumpingSkp() && persistent_cache->StoredNewShaders()) { @@ -518,43 +505,83 @@ Rasterizer::DoDrawResult Rasterizer::DoDraw( fml::RasterThreadStatus::kUnmergedNow) { return DoDrawResult{ .status = DoDrawStatus::kEnqueuePipeline, + .resubmitted_item = std::move(result.resubmitted_item), }; } } - return DoDrawResult{ - .status = status, - }; + return result; } -Rasterizer::DoDrawStatus Rasterizer::DrawToSurface( +Rasterizer::DoDrawResult Rasterizer::DrawToSurface( FrameTimingsRecorder& frame_timings_recorder, - flutter::LayerTree& layer_tree, - float device_pixel_ratio) { + std::list tasks) { TRACE_EVENT0("flutter", "Rasterizer::DrawToSurface"); FML_DCHECK(surface_); - DoDrawStatus status; + // TODO(dkwingsmt): The rasterizer only supports rendering a single view + // and that view must be the implicit view. Properly support multi-view + // in the future. + FML_CHECK(tasks.size() == 1u); + auto& task = tasks.front(); + FML_DCHECK(task.view_id == kFlutterImplicitViewId); + int64_t view_id = kFlutterImplicitViewId; + std::unique_ptr layer_tree = std::move(task.layer_tree); + float device_pixel_ratio = task.device_pixel_ratio; + if (delegate_.ShouldDiscardLayerTree(task.view_id, *layer_tree)) { + frame_timings_recorder.RecordRasterStart(fml::TimePoint::Now()); + frame_timings_recorder.RecordRasterEnd(); + return DoDrawResult{ + .status = DoDrawStatus::kDiscarded, + }; + } + + bool gpu_unavailable = false; + DrawSurfaceStatus status; if (surface_->AllowsDrawingWhenGpuDisabled()) { - status = ToDoDrawStatus(DrawToSurfaceUnsafe( - frame_timings_recorder, layer_tree, device_pixel_ratio)); + status = DrawToSurfaceUnsafe(frame_timings_recorder, *layer_tree, + device_pixel_ratio); } else { delegate_.GetIsGpuDisabledSyncSwitch()->Execute( fml::SyncSwitch::Handlers() - .SetIfTrue([&] { status = DoDrawStatus::kGpuUnavailable; }) + .SetIfTrue([&] { gpu_unavailable = true; }) .SetIfFalse([&] { - status = ToDoDrawStatus(DrawToSurfaceUnsafe( - frame_timings_recorder, layer_tree, device_pixel_ratio)); + status = DrawToSurfaceUnsafe(frame_timings_recorder, *layer_tree, + device_pixel_ratio); })); } - return status; + if (gpu_unavailable) { + frame_timings_recorder.RecordRasterStart(fml::TimePoint::Now()); + frame_timings_recorder.RecordRasterEnd(); + return DoDrawResult{ + .status = DoDrawStatus::kGpuUnavailable, + }; + } + std::unique_ptr resubmitted_item; + if (status == DrawSurfaceStatus::kSuccess) { + last_successful_tasks_.try_emplace( + /*key=*/view_id, + /*value ctor=*/view_id, std::move(layer_tree), device_pixel_ratio); + } else if (status == DrawSurfaceStatus::kRetry) { + std::list resubmitted_tasks; + resubmitted_tasks.emplace_back(kFlutterImplicitViewId, + std::move(layer_tree), device_pixel_ratio); + resubmitted_item = std::make_unique( + std::move(resubmitted_tasks), + frame_timings_recorder.CloneUntil( + FrameTimingsRecorder::State::kBuildEnd)); + } + return DoDrawResult{ + .status = ToDoDrawStatus(status), + .resubmitted_item = std::move(resubmitted_item), + }; } Rasterizer::DoDrawStatus Rasterizer::ToDoDrawStatus(DrawSurfaceStatus status) { switch (status) { case DrawSurfaceStatus::kRetry: - return DoDrawStatus::kRetry; + return DoDrawStatus::kSuccess; case DrawSurfaceStatus::kFailed: return DoDrawStatus::kFailed; default: @@ -636,7 +663,9 @@ Rasterizer::DrawSurfaceStatus Rasterizer::DrawToSurfaceUnsafe( damage = std::make_unique(); auto existing_damage = frame->framebuffer_info().existing_damage; if (existing_damage.has_value() && !force_full_repaint) { - damage->SetPreviousLayerTree(last_layer_tree_.get()); + // TODO(dkwingsmt): Use a correct view ID here. + int64_t view_id = kFlutterImplicitViewId; + damage->SetPreviousLayerTree(GetLastLayerTree(view_id)); damage->AddAdditionalDamage(existing_damage.value()); damage->SetClipAlignment( frame->framebuffer_info().horizontal_clip_alignment, @@ -656,6 +685,8 @@ Rasterizer::DrawSurfaceStatus Rasterizer::DrawToSurfaceUnsafe( damage.get() // frame damage ); if (frame_status == RasterStatus::kSkipAndRetry) { + frame_timings_recorder.RecordRasterEnd( + &compositor_context_->raster_cache()); return DrawSurfaceStatus::kRetry; } @@ -706,6 +737,7 @@ Rasterizer::DrawSurfaceStatus Rasterizer::DrawToSurfaceUnsafe( } } + frame_timings_recorder.RecordRasterEnd(&compositor_context_->raster_cache()); return DrawSurfaceStatus::kFailed; } @@ -793,7 +825,9 @@ sk_sp Rasterizer::ScreenshotLayerTreeAsImage( Rasterizer::Screenshot Rasterizer::ScreenshotLastLayerTree( Rasterizer::ScreenshotType type, bool base64_encode) { - auto* layer_tree = GetLastLayerTree(); + // TODO(dkwingsmt): Support screenshotting all last layer trees + // when the shell protocol supports multi-views. + auto* layer_tree = GetLastLayerTree(kFlutterImplicitViewId); if (layer_tree == nullptr) { FML_LOG(ERROR) << "Last layer tree was null when screenshotting."; return {}; diff --git a/shell/common/rasterizer.h b/shell/common/rasterizer.h index 700e4a6ecf0ce..de6d18d83f2f4 100644 --- a/shell/common/rasterizer.h +++ b/shell/common/rasterizer.h @@ -7,6 +7,7 @@ #include #include +#include #include "flutter/common/settings.h" #include "flutter/common/task_runners.h" @@ -197,6 +198,7 @@ class Rasterizer final : public SnapshotDelegate, /// collects associated resources. No more rendering may occur /// till the next call to `Rasterizer::Setup` with a new render /// surface. Calling a teardown without a setup is user error. + /// Calling this method for multiple times is safe. /// void Teardown(); @@ -251,7 +253,7 @@ class Rasterizer final : public SnapshotDelegate, /// @return A pointer to the last layer or `nullptr` if this rasterizer /// has never rendered a frame. /// - flutter::LayerTree* GetLastLayerTree(); + flutter::LayerTree* GetLastLayerTree(int64_t view_id); //---------------------------------------------------------------------------- /// @brief Draws a last layer tree to the render surface. This may seem @@ -528,6 +530,13 @@ class Rasterizer final : public SnapshotDelegate, /// void DisableThreadMergerIfNeeded(); + //---------------------------------------------------------------------------- + /// @brief Returns whether TearDown has been called. + /// + /// This method is only used only in unit tests. + /// + bool IsTornDown(); + private: // The result status of DrawToSurfaceUnsafe. enum class DrawSurfaceStatus { @@ -551,16 +560,6 @@ class Rasterizer final : public SnapshotDelegate, enum class DoDrawStatus { // Frame has been successfully rasterized. kSuccess, - // Frame should be submitted again. - // - // This can occur on Android when switching the background surface to - // FlutterImageView. On Android, the first frame doesn't make the image - // available to the ImageReader right away. The second frame does. - // TODO(egarciad): https://github.com/flutter/flutter/issues/65652 - // - // This can also occur when the frame is dropped to wait for the thread - // merger to merge the raster and platform threads. - kRetry, // Frame has been successfully rasterized, but there are additional items // in the pipeline waiting to be consumed. This is currently only used when // thread configuration change occurs. @@ -643,13 +642,13 @@ class Rasterizer final : public SnapshotDelegate, DoDrawResult DoDraw( std::unique_ptr frame_timings_recorder, - std::unique_ptr layer_tree, - float device_pixel_ratio); + std::list tasks); - DoDrawStatus DrawToSurface(FrameTimingsRecorder& frame_timings_recorder, - flutter::LayerTree& layer_tree, - float device_pixel_ratio); + // After this method, the frame timing recorder is at raster end. + DoDrawResult DrawToSurface(FrameTimingsRecorder& frame_timings_recorder, + std::list tasks); + // After this method, the frame timing recorder is at raster end. DrawSurfaceStatus DrawToSurfaceUnsafe( FrameTimingsRecorder& frame_timings_recorder, flutter::LayerTree& layer_tree, @@ -657,18 +656,18 @@ class Rasterizer final : public SnapshotDelegate, void FireNextFrameCallbackIfPresent(); + static bool ShouldResubmitFrame(const DoDrawResult& result); static DoDrawStatus ToDoDrawStatus(DrawSurfaceStatus status); static DrawStatus ToDrawStatus(DoDrawStatus status); + bool is_torn_down_; Delegate& delegate_; MakeGpuImageBehavior gpu_image_behavior_; std::weak_ptr impeller_context_; std::unique_ptr surface_; std::unique_ptr snapshot_surface_producer_; std::unique_ptr compositor_context_; - // This is the last successfully rasterized layer tree. - std::unique_ptr last_layer_tree_; - float last_device_pixel_ratio_; + std::unordered_map last_successful_tasks_; fml::closure next_frame_callback_; bool user_override_resource_cache_bytes_; std::optional max_cache_bytes_; diff --git a/shell/common/shell.cc b/shell/common/shell.cc index 261a41fff2767..ca3d591c39d15 100644 --- a/shell/common/shell.cc +++ b/shell/common/shell.cc @@ -1966,7 +1966,8 @@ bool Shell::OnServiceProtocolRenderFrameWithRasterStats( // TODO(dkwingsmt): This method only handles view #0, including the snapshot // and the frame size. We need to adapt this method to multi-view. // https://github.com/flutter/flutter/issues/131892 - if (auto last_layer_tree = rasterizer_->GetLastLayerTree()) { + int64_t view_id = kFlutterImplicitViewId; + if (auto last_layer_tree = rasterizer_->GetLastLayerTree(view_id)) { auto& allocator = response->GetAllocator(); response->SetObject(); response->AddMember("type", "RenderFrameWithRasterStats", allocator); @@ -1997,7 +1998,7 @@ bool Shell::OnServiceProtocolRenderFrameWithRasterStats( response->AddMember("snapshots", snapshots, allocator); - const auto& frame_size = ExpectedFrameSize(kFlutterImplicitViewId); + const auto& frame_size = ExpectedFrameSize(view_id); response->AddMember("frame_width", frame_size.width(), allocator); response->AddMember("frame_height", frame_size.height(), allocator); diff --git a/shell/common/shell_unittests.cc b/shell/common/shell_unittests.cc index 2371fa9113aa7..f899d5c5ede97 100644 --- a/shell/common/shell_unittests.cc +++ b/shell/common/shell_unittests.cc @@ -310,30 +310,26 @@ static bool ValidateShell(Shell* shell) { return true; } -static bool RasterizerHasLayerTree(Shell* shell) { +static bool RasterizerIsTornDown(Shell* shell) { fml::AutoResetWaitableEvent latch; - bool has_layer_tree = false; + bool is_torn_down = false; fml::TaskRunner::RunNowOrPostTask( shell->GetTaskRunners().GetRasterTaskRunner(), - [shell, &latch, &has_layer_tree]() { - has_layer_tree = shell->GetRasterizer()->GetLastLayerTree() != nullptr; + [shell, &latch, &is_torn_down]() { + is_torn_down = shell->GetRasterizer()->IsTornDown(); latch.Signal(); }); latch.Wait(); - return has_layer_tree; + return is_torn_down; } static void ValidateDestroyPlatformView(Shell* shell) { ASSERT_TRUE(shell != nullptr); ASSERT_TRUE(shell->IsSetup()); - // To validate destroy platform view, we must ensure the rasterizer has a - // layer tree before the platform view is destroyed. - ASSERT_TRUE(RasterizerHasLayerTree(shell)); - + ASSERT_FALSE(RasterizerIsTornDown(shell)); ShellTest::PlatformViewNotifyDestroyed(shell); - // Validate the layer tree is destroyed - ASSERT_FALSE(RasterizerHasLayerTree(shell)); + ASSERT_TRUE(RasterizerIsTornDown(shell)); } static std::string CreateFlagsString(std::vector& flags) { From c267f089553de9d39bce6c85f076016604a02dcf Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Thu, 7 Sep 2023 23:28:47 -0700 Subject: [PATCH 21/48] Replace successful tasks --- shell/common/rasterizer.cc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index 9233df0a899fe..990556884dcab 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -560,13 +560,13 @@ Rasterizer::DoDrawResult Rasterizer::DrawToSurface( } std::unique_ptr resubmitted_item; if (status == DrawSurfaceStatus::kSuccess) { - last_successful_tasks_.try_emplace( - /*key=*/view_id, - /*value ctor=*/view_id, std::move(layer_tree), device_pixel_ratio); + last_successful_tasks_.insert_or_assign( + view_id, + LayerTreeTask(view_id, std::move(layer_tree), device_pixel_ratio)); } else if (status == DrawSurfaceStatus::kRetry) { std::list resubmitted_tasks; - resubmitted_tasks.emplace_back(kFlutterImplicitViewId, - std::move(layer_tree), device_pixel_ratio); + resubmitted_tasks.emplace_back(view_id, std::move(layer_tree), + device_pixel_ratio); resubmitted_item = std::make_unique( std::move(resubmitted_tasks), frame_timings_recorder.CloneUntil( From c30257e12885cd4a72922ea301f92513fb3f6cae Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Fri, 8 Sep 2023 00:30:49 -0700 Subject: [PATCH 22/48] Fix enqueuepipeline --- shell/common/rasterizer.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index 990556884dcab..09aab81519037 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -284,6 +284,8 @@ bool Rasterizer::ShouldResubmitFrame(const DoDrawResult& result) { DrawStatus Rasterizer::ToDrawStatus(DoDrawStatus status) { switch (status) { + case DoDrawStatus::kEnqueuePipeline: + return DrawStatus::kSuccess; case DoDrawStatus::kGpuUnavailable: return DrawStatus::kGpuUnavailable; case DoDrawStatus::kDiscarded: From 21fdea90ac152fecf5faa2ae96d63cec8773e73d Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Fri, 8 Sep 2023 10:01:54 -0700 Subject: [PATCH 23/48] DrawToSurfaces and DrawToSurfacesUnsafe --- shell/common/rasterizer.cc | 60 +++++++++++++++++++++----------------- shell/common/rasterizer.h | 15 ++++++---- 2 files changed, 44 insertions(+), 31 deletions(-) diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index 09aab81519037..a0360eead6296 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -195,7 +195,7 @@ void Rasterizer::DrawLastLayerTree( last_successful_tasks_.clear(); DoDrawResult result = - DrawToSurface(*frame_timings_recorder, std::move(tasks)); + DrawToSurfaces(*frame_timings_recorder, std::move(tasks)); // EndFrame should perform cleanups for the external_view_embedder. if (external_view_embedder_ && external_view_embedder_->GetUsedThisFrame()) { @@ -432,7 +432,7 @@ Rasterizer::DoDrawResult Rasterizer::DoDraw( persistent_cache->ResetStoredNewShaders(); DoDrawResult result = - DrawToSurface(*frame_timings_recorder, std::move(tasks)); + DrawToSurfaces(*frame_timings_recorder, std::move(tasks)); FML_DCHECK(result.status != DoDrawStatus::kEnqueuePipeline); if (result.status == DoDrawStatus::kGpuUnavailable) { return DoDrawResult{ @@ -515,12 +515,39 @@ Rasterizer::DoDrawResult Rasterizer::DoDraw( return result; } -Rasterizer::DoDrawResult Rasterizer::DrawToSurface( +Rasterizer::DoDrawResult Rasterizer::DrawToSurfaces( FrameTimingsRecorder& frame_timings_recorder, std::list tasks) { - TRACE_EVENT0("flutter", "Rasterizer::DrawToSurface"); + TRACE_EVENT0("flutter", "Rasterizer::DrawToSurfaces"); FML_DCHECK(surface_); + bool gpu_unavailable = false; + DoDrawResult result; + if (surface_->AllowsDrawingWhenGpuDisabled()) { + result = DrawToSurfacesUnsafe(frame_timings_recorder, std::move(tasks)); + } else { + delegate_.GetIsGpuDisabledSyncSwitch()->Execute( + fml::SyncSwitch::Handlers() + .SetIfTrue([&] { gpu_unavailable = true; }) + .SetIfFalse([&] { + result = DrawToSurfacesUnsafe(frame_timings_recorder, + std::move(tasks)); + })); + } + + if (gpu_unavailable) { + frame_timings_recorder.RecordRasterStart(fml::TimePoint::Now()); + frame_timings_recorder.RecordRasterEnd(); + return DoDrawResult{ + .status = DoDrawStatus::kGpuUnavailable, + }; + } + return result; +} + +Rasterizer::DoDrawResult Rasterizer::DrawToSurfacesUnsafe( + FrameTimingsRecorder& frame_timings_recorder, + std::list tasks) { // TODO(dkwingsmt): The rasterizer only supports rendering a single view // and that view must be the implicit view. Properly support multi-view // in the future. @@ -538,28 +565,9 @@ Rasterizer::DoDrawResult Rasterizer::DrawToSurface( }; } - bool gpu_unavailable = false; - DrawSurfaceStatus status; - if (surface_->AllowsDrawingWhenGpuDisabled()) { - status = DrawToSurfaceUnsafe(frame_timings_recorder, *layer_tree, - device_pixel_ratio); - } else { - delegate_.GetIsGpuDisabledSyncSwitch()->Execute( - fml::SyncSwitch::Handlers() - .SetIfTrue([&] { gpu_unavailable = true; }) - .SetIfFalse([&] { - status = DrawToSurfaceUnsafe(frame_timings_recorder, *layer_tree, - device_pixel_ratio); - })); - } + DrawSurfaceStatus status = DrawToSurfaceUnsafe( + frame_timings_recorder, *layer_tree, device_pixel_ratio); - if (gpu_unavailable) { - frame_timings_recorder.RecordRasterStart(fml::TimePoint::Now()); - frame_timings_recorder.RecordRasterEnd(); - return DoDrawResult{ - .status = DoDrawStatus::kGpuUnavailable, - }; - } std::unique_ptr resubmitted_item; if (status == DrawSurfaceStatus::kSuccess) { last_successful_tasks_.insert_or_assign( @@ -594,7 +602,7 @@ Rasterizer::DoDrawStatus Rasterizer::ToDoDrawStatus(DrawSurfaceStatus status) { /// Unsafe because it assumes we have access to the GPU which isn't the case /// when iOS is backgrounded, for example. -/// \see Rasterizer::DrawToSurface +/// \see Rasterizer::DrawToSurfaces Rasterizer::DrawSurfaceStatus Rasterizer::DrawToSurfaceUnsafe( FrameTimingsRecorder& frame_timings_recorder, flutter::LayerTree& layer_tree, diff --git a/shell/common/rasterizer.h b/shell/common/rasterizer.h index de6d18d83f2f4..c231e02499e2d 100644 --- a/shell/common/rasterizer.h +++ b/shell/common/rasterizer.h @@ -556,7 +556,7 @@ class Rasterizer final : public SnapshotDelegate, kFailed, }; - // The result status of DoDraw and DrawToSurface. + // The result status of DoDraw, DrawToSurfaces, and DrawToSurfacesUnsafe. enum class DoDrawStatus { // Frame has been successfully rasterized. kSuccess, @@ -644,11 +644,16 @@ class Rasterizer final : public SnapshotDelegate, std::unique_ptr frame_timings_recorder, std::list tasks); - // After this method, the frame timing recorder is at raster end. - DoDrawResult DrawToSurface(FrameTimingsRecorder& frame_timings_recorder, - std::list tasks); + // This method pushes the frame timing recorder from build end to raster end. + DoDrawResult DrawToSurfaces(FrameTimingsRecorder& frame_timings_recorder, + std::list tasks); - // After this method, the frame timing recorder is at raster end. + // This method pushes the frame timing recorder from build end to raster end. + DoDrawResult DrawToSurfacesUnsafe( + FrameTimingsRecorder& frame_timings_recorder, + std::list tasks); + + // This method pushes the frame timing recorder from build end to raster end. DrawSurfaceStatus DrawToSurfaceUnsafe( FrameTimingsRecorder& frame_timings_recorder, flutter::LayerTree& layer_tree, From 9bdb8418ea148982a0dbd434551c5b1d18c76fc4 Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Fri, 8 Sep 2023 14:30:17 -0700 Subject: [PATCH 24/48] Fix test --- shell/common/rasterizer_unittests.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/shell/common/rasterizer_unittests.cc b/shell/common/rasterizer_unittests.cc index 4d791a560f048..72b532c3a2f1b 100644 --- a/shell/common/rasterizer_unittests.cc +++ b/shell/common/rasterizer_unittests.cc @@ -523,6 +523,10 @@ TEST(RasterizerTest, externalViewEmbedderDoesntEndFrameWhenNotUsedThisFrame) { ON_CALL(delegate, GetSettings()).WillByDefault(ReturnRef(settings)); EXPECT_CALL(delegate, GetTaskRunners()) .WillRepeatedly(ReturnRef(task_runners)); + auto is_gpu_disabled_sync_switch = + std::make_shared(false); + ON_CALL(delegate, GetIsGpuDisabledSyncSwitch()) + .WillByDefault(Return(is_gpu_disabled_sync_switch)); auto rasterizer = std::make_unique(delegate); auto surface = std::make_unique>(); From cf82d5f6aea92eb6456169c9e0b08029c2d655af Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Fri, 8 Sep 2023 15:22:43 -0700 Subject: [PATCH 25/48] Move frame timing recorder out of surface --- shell/common/rasterizer.cc | 70 +++++++++++++++++++------------------- shell/common/rasterizer.h | 8 +++-- 2 files changed, 40 insertions(+), 38 deletions(-) diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index a0360eead6296..95eef71d64a48 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -528,7 +528,11 @@ Rasterizer::DoDrawResult Rasterizer::DrawToSurfaces( } else { delegate_.GetIsGpuDisabledSyncSwitch()->Execute( fml::SyncSwitch::Handlers() - .SetIfTrue([&] { gpu_unavailable = true; }) + .SetIfTrue([&] { + gpu_unavailable = true; + frame_timings_recorder.RecordRasterStart(fml::TimePoint::Now()); + frame_timings_recorder.RecordRasterEnd(); + }) .SetIfFalse([&] { result = DrawToSurfacesUnsafe(frame_timings_recorder, std::move(tasks)); @@ -536,8 +540,6 @@ Rasterizer::DoDrawResult Rasterizer::DrawToSurfaces( } if (gpu_unavailable) { - frame_timings_recorder.RecordRasterStart(fml::TimePoint::Now()); - frame_timings_recorder.RecordRasterEnd(); return DoDrawResult{ .status = DoDrawStatus::kGpuUnavailable, }; @@ -554,11 +556,27 @@ Rasterizer::DoDrawResult Rasterizer::DrawToSurfacesUnsafe( FML_CHECK(tasks.size() == 1u); auto& task = tasks.front(); FML_DCHECK(task.view_id == kFlutterImplicitViewId); + + std::optional presentation_time = std::nullopt; + // TODO (https://github.com/flutter/flutter/issues/105596): this can be in + // the past and might need to get snapped to future as this frame could + // have been resubmitted. `presentation_time` on SubmitInfo is not set + // in this case. + { + const auto vsync_target_time = frame_timings_recorder.GetVsyncTargetTime(); + if (vsync_target_time > fml::TimePoint::Now()) { + presentation_time = vsync_target_time; + } + } + + compositor_context_->ui_time().SetLapTime( + frame_timings_recorder.GetBuildDuration()); + frame_timings_recorder.RecordRasterStart(fml::TimePoint::Now()); + int64_t view_id = kFlutterImplicitViewId; std::unique_ptr layer_tree = std::move(task.layer_tree); float device_pixel_ratio = task.device_pixel_ratio; if (delegate_.ShouldDiscardLayerTree(task.view_id, *layer_tree)) { - frame_timings_recorder.RecordRasterStart(fml::TimePoint::Now()); frame_timings_recorder.RecordRasterEnd(); return DoDrawResult{ .status = DoDrawStatus::kDiscarded, @@ -566,7 +584,7 @@ Rasterizer::DoDrawResult Rasterizer::DrawToSurfacesUnsafe( } DrawSurfaceStatus status = DrawToSurfaceUnsafe( - frame_timings_recorder, *layer_tree, device_pixel_ratio); + view_id, *layer_tree, device_pixel_ratio, presentation_time); std::unique_ptr resubmitted_item; if (status == DrawSurfaceStatus::kSuccess) { @@ -582,6 +600,14 @@ Rasterizer::DoDrawResult Rasterizer::DrawToSurfacesUnsafe( frame_timings_recorder.CloneUntil( FrameTimingsRecorder::State::kBuildEnd)); } + + frame_timings_recorder.RecordRasterEnd(&compositor_context_->raster_cache()); + FireNextFrameCallbackIfPresent(); + + if (surface_->GetContext()) { + surface_->GetContext()->performDeferredCleanup(kSkiaCleanupExpiration); + } + return DoDrawResult{ .status = ToDoDrawStatus(status), .resubmitted_item = std::move(resubmitted_item), @@ -604,14 +630,12 @@ Rasterizer::DoDrawStatus Rasterizer::ToDoDrawStatus(DrawSurfaceStatus status) { /// when iOS is backgrounded, for example. /// \see Rasterizer::DrawToSurfaces Rasterizer::DrawSurfaceStatus Rasterizer::DrawToSurfaceUnsafe( - FrameTimingsRecorder& frame_timings_recorder, + int64_t view_id, flutter::LayerTree& layer_tree, - float device_pixel_ratio) { + float device_pixel_ratio, + std::optional presentation_time) { FML_DCHECK(surface_); - compositor_context_->ui_time().SetLapTime( - frame_timings_recorder.GetBuildDuration()); - DlCanvas* embedder_root_canvas = nullptr; if (external_view_embedder_) { FML_DCHECK(!external_view_embedder_->GetUsedThisFrame()); @@ -622,16 +646,12 @@ Rasterizer::DrawSurfaceStatus Rasterizer::DrawToSurfaceUnsafe( embedder_root_canvas = external_view_embedder_->GetRootCanvas(); } - frame_timings_recorder.RecordRasterStart(fml::TimePoint::Now()); - // On Android, the external view embedder deletes surfaces in `BeginFrame`. // // Deleting a surface also clears the GL context. Therefore, acquire the // frame after calling `BeginFrame` as this operation resets the GL context. auto frame = surface_->AcquireFrame(layer_tree.frame_size()); if (frame == nullptr) { - frame_timings_recorder.RecordRasterEnd( - &compositor_context_->raster_cache()); return DrawSurfaceStatus::kFailed; } @@ -673,8 +693,6 @@ Rasterizer::DrawSurfaceStatus Rasterizer::DrawToSurfaceUnsafe( damage = std::make_unique(); auto existing_damage = frame->framebuffer_info().existing_damage; if (existing_damage.has_value() && !force_full_repaint) { - // TODO(dkwingsmt): Use a correct view ID here. - int64_t view_id = kFlutterImplicitViewId; damage->SetPreviousLayerTree(GetLastLayerTree(view_id)); damage->AddAdditionalDamage(existing_damage.value()); damage->SetClipAlignment( @@ -695,20 +713,11 @@ Rasterizer::DrawSurfaceStatus Rasterizer::DrawToSurfaceUnsafe( damage.get() // frame damage ); if (frame_status == RasterStatus::kSkipAndRetry) { - frame_timings_recorder.RecordRasterEnd( - &compositor_context_->raster_cache()); return DrawSurfaceStatus::kRetry; } SurfaceFrame::SubmitInfo submit_info; - // TODO (https://github.com/flutter/flutter/issues/105596): this can be in - // the past and might need to get snapped to future as this frame could - // have been resubmitted. `presentation_time` on `submit_info` is not set - // in this case. - const auto presentation_time = frame_timings_recorder.GetVsyncTargetTime(); - if (presentation_time > fml::TimePoint::Now()) { - submit_info.presentation_time = presentation_time; - } + submit_info.presentation_time = presentation_time; if (damage) { submit_info.frame_damage = damage->GetFrameDamage(); submit_info.buffer_damage = damage->GetBufferDamage(); @@ -731,14 +740,6 @@ Rasterizer::DrawSurfaceStatus Rasterizer::DrawToSurfaceUnsafe( compositor_context_->raster_cache().EndFrame(); } - frame_timings_recorder.RecordRasterEnd( - &compositor_context_->raster_cache()); - FireNextFrameCallbackIfPresent(); - - if (surface_->GetContext()) { - surface_->GetContext()->performDeferredCleanup(kSkiaCleanupExpiration); - } - if (frame_status == RasterStatus::kResubmit) { return DrawSurfaceStatus::kRetry; } else { @@ -747,7 +748,6 @@ Rasterizer::DrawSurfaceStatus Rasterizer::DrawToSurfaceUnsafe( } } - frame_timings_recorder.RecordRasterEnd(&compositor_context_->raster_cache()); return DrawSurfaceStatus::kFailed; } diff --git a/shell/common/rasterizer.h b/shell/common/rasterizer.h index c231e02499e2d..0014402b40d88 100644 --- a/shell/common/rasterizer.h +++ b/shell/common/rasterizer.h @@ -653,11 +653,13 @@ class Rasterizer final : public SnapshotDelegate, FrameTimingsRecorder& frame_timings_recorder, std::list tasks); - // This method pushes the frame timing recorder from build end to raster end. + // This method is not affiliated with the frame timing recorder, but should be + // included within the raster phase. DrawSurfaceStatus DrawToSurfaceUnsafe( - FrameTimingsRecorder& frame_timings_recorder, + int64_t view_id, flutter::LayerTree& layer_tree, - float device_pixel_ratio); + float device_pixel_ratio, + std::optional presentation_time); void FireNextFrameCallbackIfPresent(); From 21530fb07d767236f1127d4cb9d52b8cf15f4065 Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Sun, 10 Sep 2023 16:58:49 -0700 Subject: [PATCH 26/48] Move status out --- shell/common/rasterizer.cc | 80 ++++++++++++---------------- shell/common/rasterizer.h | 68 +++++++++++++---------- shell/common/rasterizer_unittests.cc | 8 ++- 3 files changed, 79 insertions(+), 77 deletions(-) diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index b61478e5848c9..7d2d6b1aacb6b 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -133,6 +133,11 @@ bool Rasterizer::IsTornDown() { return is_torn_down_; } +std::optional Rasterizer::GetLastDrawStatus( + int64_t view_id) { + return last_draw_status_; +} + void Rasterizer::EnableThreadMergerIfNeeded() { if (raster_thread_merger_) { raster_thread_merger_->Enable(); @@ -289,10 +294,8 @@ DrawStatus Rasterizer::ToDrawStatus(DoDrawStatus status) { return DrawStatus::kSuccess; case DoDrawStatus::kGpuUnavailable: return DrawStatus::kGpuUnavailable; - case DoDrawStatus::kDiscarded: - return DrawStatus::kDiscarded; - case DoDrawStatus::kFailed: - return DrawStatus::kFailed; + case DoDrawStatus::kContextUnavailable: + return DrawStatus::kContextUnavailable; default: FML_CHECK(status == DoDrawStatus::kSuccess) << "Unrecognized status " << (int)status; @@ -425,7 +428,7 @@ Rasterizer::DoDrawResult Rasterizer::DoDraw( if (!surface_) { return DoDrawResult{ - .status = DoDrawStatus::kFailed, + .status = DoDrawStatus::kContextUnavailable, }; } @@ -522,31 +525,30 @@ Rasterizer::DoDrawResult Rasterizer::DrawToSurfaces( TRACE_EVENT0("flutter", "Rasterizer::DrawToSurfaces"); FML_DCHECK(surface_); - bool gpu_unavailable = false; - DoDrawResult result; + DoDrawResult result{ + .status = DoDrawStatus::kSuccess, + }; if (surface_->AllowsDrawingWhenGpuDisabled()) { - result = DrawToSurfacesUnsafe(frame_timings_recorder, std::move(tasks)); + result.resubmitted_item = + DrawToSurfacesUnsafe(frame_timings_recorder, std::move(tasks)); } else { delegate_.GetIsGpuDisabledSyncSwitch()->Execute( fml::SyncSwitch::Handlers() - .SetIfTrue([&] { gpu_unavailable = true; }) + .SetIfTrue([&] { + result.status = DoDrawStatus::kGpuUnavailable; + frame_timings_recorder.RecordRasterStart(fml::TimePoint::Now()); + frame_timings_recorder.RecordRasterEnd(); + }) .SetIfFalse([&] { - result = DrawToSurfacesUnsafe(frame_timings_recorder, - std::move(tasks)); + result.resubmitted_item = DrawToSurfacesUnsafe( + frame_timings_recorder, std::move(tasks)); })); } - if (gpu_unavailable) { - frame_timings_recorder.RecordRasterStart(fml::TimePoint::Now()); - frame_timings_recorder.RecordRasterEnd(); - return DoDrawResult{ - .status = DoDrawStatus::kGpuUnavailable, - }; - } return result; } -Rasterizer::DoDrawResult Rasterizer::DrawToSurfacesUnsafe( +std::unique_ptr Rasterizer::DrawToSurfacesUnsafe( FrameTimingsRecorder& frame_timings_recorder, std::list tasks) { // TODO(dkwingsmt): The rasterizer only supports rendering a single view @@ -558,16 +560,11 @@ Rasterizer::DoDrawResult Rasterizer::DrawToSurfacesUnsafe( int64_t view_id = kFlutterImplicitViewId; std::unique_ptr layer_tree = std::move(task.layer_tree); float device_pixel_ratio = task.device_pixel_ratio; - if (delegate_.ShouldDiscardLayerTree(task.view_id, *layer_tree)) { - frame_timings_recorder.RecordRasterStart(fml::TimePoint::Now()); - frame_timings_recorder.RecordRasterEnd(); - return DoDrawResult{ - .status = DoDrawStatus::kDiscarded, - }; - } DrawSurfaceStatus status = DrawToSurfaceUnsafe( - frame_timings_recorder, *layer_tree, device_pixel_ratio); + frame_timings_recorder, view_id, *layer_tree, device_pixel_ratio); + + last_draw_status_ = status; std::unique_ptr resubmitted_item; if (status == DrawSurfaceStatus::kSuccess) { @@ -583,33 +580,22 @@ Rasterizer::DoDrawResult Rasterizer::DrawToSurfacesUnsafe( frame_timings_recorder.CloneUntil( FrameTimingsRecorder::State::kBuildEnd)); } - return DoDrawResult{ - .status = ToDoDrawStatus(status), - .resubmitted_item = std::move(resubmitted_item), - }; -} - -Rasterizer::DoDrawStatus Rasterizer::ToDoDrawStatus(DrawSurfaceStatus status) { - switch (status) { - case DrawSurfaceStatus::kRetry: - return DoDrawStatus::kSuccess; - case DrawSurfaceStatus::kFailed: - return DoDrawStatus::kFailed; - default: - FML_CHECK(status == DrawSurfaceStatus::kSuccess); - return DoDrawStatus::kSuccess; - } + return resubmitted_item; } -/// Unsafe because it assumes we have access to the GPU which isn't the case -/// when iOS is backgrounded, for example. -/// \see Rasterizer::DrawToSurfaces -Rasterizer::DrawSurfaceStatus Rasterizer::DrawToSurfaceUnsafe( +DrawSurfaceStatus Rasterizer::DrawToSurfaceUnsafe( FrameTimingsRecorder& frame_timings_recorder, + int64_t view_id, flutter::LayerTree& layer_tree, float device_pixel_ratio) { FML_DCHECK(surface_); + if (delegate_.ShouldDiscardLayerTree(view_id, layer_tree)) { + frame_timings_recorder.RecordRasterStart(fml::TimePoint::Now()); + frame_timings_recorder.RecordRasterEnd(); + return DrawSurfaceStatus::kDiscarded; + } + compositor_context_->ui_time().SetLapTime( frame_timings_recorder.GetBuildDuration()); diff --git a/shell/common/rasterizer.h b/shell/common/rasterizer.h index c231e02499e2d..9fb8d03660127 100644 --- a/shell/common/rasterizer.h +++ b/shell/common/rasterizer.h @@ -53,10 +53,8 @@ namespace flutter { enum class DrawStatus { // Frame has been successfully rasterized. kSuccess, - // Failed to rasterize the frame. - kFailed, - // Layer tree was discarded due to LayerTreeDiscardCallback. - kDiscarded, + // Failed to rasterize the frame because the rendering context is unavailable. + kContextUnavailable, // Nothing was done, because the call was not on the raster thread. Yielded to // let this frame be serviced on the right thread. kYielded, @@ -66,6 +64,26 @@ enum class DrawStatus { kGpuUnavailable, }; +// The result status of DrawToSurfaceUnsafe. +enum class DrawSurfaceStatus { + // Frame has been successfully rasterized. + kSuccess, + // Frame should be submitted again. + // + // This can occur on Android when switching the background surface to + // FlutterImageView. On Android, the first frame doesn't make the image + // available to the ImageReader right away. The second frame does. + // TODO(egarciad): https://github.com/flutter/flutter/issues/65652 + // + // This can also occur when the frame is dropped to wait for the thread + // merger to merge the raster and platform threads. + kRetry, + // Failed to rasterize the frame. + kFailed, + // Layer tree was discarded due to LayerTreeDiscardCallback. + kDiscarded, +}; + //------------------------------------------------------------------------------ /// The rasterizer is a component owned by the shell that resides on the raster /// task runner. Each shell owns exactly one instance of a rasterizer. The @@ -537,25 +555,14 @@ class Rasterizer final : public SnapshotDelegate, /// bool IsTornDown(); - private: - // The result status of DrawToSurfaceUnsafe. - enum class DrawSurfaceStatus { - // Frame has been successfully rasterized. - kSuccess, - // Frame should be submitted again. - // - // This can occur on Android when switching the background surface to - // FlutterImageView. On Android, the first frame doesn't make the image - // available to the ImageReader right away. The second frame does. - // TODO(egarciad): https://github.com/flutter/flutter/issues/65652 - // - // This can also occur when the frame is dropped to wait for the thread - // merger to merge the raster and platform threads. - kRetry, - // Failed to rasterize the frame. - kFailed, - }; + //---------------------------------------------------------------------------- + /// @brief Returns the last status of drawing the specific view. + /// + /// This method is only used only in unit tests. + /// + std::optional GetLastDrawStatus(int64_t view_id); + private: // The result status of DoDraw, DrawToSurfaces, and DrawToSurfacesUnsafe. enum class DoDrawStatus { // Frame has been successfully rasterized. @@ -564,10 +571,9 @@ class Rasterizer final : public SnapshotDelegate, // in the pipeline waiting to be consumed. This is currently only used when // thread configuration change occurs. kEnqueuePipeline, - // Failed to rasterize the frame. - kFailed, - // Layer tree was discarded due to LayerTreeDiscardCallback. - kDiscarded, + // Failed to rasterize the frame because the rendering context is + // unavailable. + kContextUnavailable, // Layer tree was discarded due to inability to access the GPU. kGpuUnavailable, }; @@ -648,21 +654,25 @@ class Rasterizer final : public SnapshotDelegate, DoDrawResult DrawToSurfaces(FrameTimingsRecorder& frame_timings_recorder, std::list tasks); + // Unsafe because it assumes we have access to the GPU which isn't the case + // when iOS is backgrounded, for example. + // \see Rasterizer::DrawToSurfaces + // // This method pushes the frame timing recorder from build end to raster end. - DoDrawResult DrawToSurfacesUnsafe( + std::unique_ptr DrawToSurfacesUnsafe( FrameTimingsRecorder& frame_timings_recorder, std::list tasks); // This method pushes the frame timing recorder from build end to raster end. DrawSurfaceStatus DrawToSurfaceUnsafe( FrameTimingsRecorder& frame_timings_recorder, + int64_t view_id, flutter::LayerTree& layer_tree, float device_pixel_ratio); void FireNextFrameCallbackIfPresent(); static bool ShouldResubmitFrame(const DoDrawResult& result); - static DoDrawStatus ToDoDrawStatus(DrawSurfaceStatus status); static DrawStatus ToDrawStatus(DoDrawStatus status); bool is_torn_down_; @@ -680,6 +690,8 @@ class Rasterizer final : public SnapshotDelegate, std::shared_ptr external_view_embedder_; std::unique_ptr snapshot_controller_; + DrawSurfaceStatus last_draw_status_; + // WeakPtrFactory must be the last member. fml::TaskRunnerAffineWeakPtrFactory weak_factory_; FML_DISALLOW_COPY_AND_ASSIGN(Rasterizer); diff --git a/shell/common/rasterizer_unittests.cc b/shell/common/rasterizer_unittests.cc index 72b532c3a2f1b..71cea73ed6a6f 100644 --- a/shell/common/rasterizer_unittests.cc +++ b/shell/common/rasterizer_unittests.cc @@ -565,7 +565,9 @@ TEST(RasterizerTest, externalViewEmbedderDoesntEndFrameWhenNotUsedThisFrame) { // Always discard the layer tree. ON_CALL(delegate, ShouldDiscardLayerTree).WillByDefault(Return(true)); DrawStatus status = rasterizer->Draw(pipeline); - EXPECT_EQ(status, DrawStatus::kDiscarded); + EXPECT_EQ(status, DrawStatus::kSuccess); + EXPECT_EQ(rasterizer->GetLastDrawStatus(kImplicitViewId), + DrawSurfaceStatus::kDiscarded); latch.Signal(); }); latch.Wait(); @@ -901,7 +903,9 @@ TEST( EXPECT_TRUE(result.success); ON_CALL(delegate, ShouldDiscardLayerTree).WillByDefault(Return(false)); DrawStatus status = rasterizer->Draw(pipeline); - EXPECT_EQ(status, DrawStatus::kFailed); + EXPECT_EQ(status, DrawStatus::kSuccess); + EXPECT_EQ(rasterizer->GetLastDrawStatus(kImplicitViewId), + DrawSurfaceStatus::kFailed); latch.Signal(); }); latch.Wait(); From 65ec5bd0831dd198b652cab5d571502899a11904 Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Sun, 10 Sep 2023 20:59:57 -0700 Subject: [PATCH 27/48] Rename to kDone, kNotSetup, and doc --- shell/common/rasterizer.cc | 16 +++++------ shell/common/rasterizer.h | 40 +++++++++++++++++----------- shell/common/rasterizer_unittests.cc | 8 +++--- 3 files changed, 36 insertions(+), 28 deletions(-) diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index 7d2d6b1aacb6b..ef52db0349e6d 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -228,7 +228,7 @@ DrawStatus Rasterizer::Draw( LayerTreePipeline::Consumer consumer = [&draw_result, this]( std::unique_ptr item) { if (item->tasks.empty()) { - draw_result.status = DoDrawStatus::kSuccess; + draw_result.status = DoDrawStatus::kDone; return; } draw_result = @@ -291,15 +291,15 @@ bool Rasterizer::ShouldResubmitFrame(const DoDrawResult& result) { DrawStatus Rasterizer::ToDrawStatus(DoDrawStatus status) { switch (status) { case DoDrawStatus::kEnqueuePipeline: - return DrawStatus::kSuccess; + return DrawStatus::kDone; case DoDrawStatus::kGpuUnavailable: return DrawStatus::kGpuUnavailable; - case DoDrawStatus::kContextUnavailable: - return DrawStatus::kContextUnavailable; + case DoDrawStatus::kNotSetUp: + return DrawStatus::kNotSetUp; default: - FML_CHECK(status == DoDrawStatus::kSuccess) + FML_CHECK(status == DoDrawStatus::kDone) << "Unrecognized status " << (int)status; - return DrawStatus::kSuccess; + return DrawStatus::kDone; } } @@ -428,7 +428,7 @@ Rasterizer::DoDrawResult Rasterizer::DoDraw( if (!surface_) { return DoDrawResult{ - .status = DoDrawStatus::kContextUnavailable, + .status = DoDrawStatus::kNotSetUp, }; } @@ -526,7 +526,7 @@ Rasterizer::DoDrawResult Rasterizer::DrawToSurfaces( FML_DCHECK(surface_); DoDrawResult result{ - .status = DoDrawStatus::kSuccess, + .status = DoDrawStatus::kDone, }; if (surface_->AllowsDrawingWhenGpuDisabled()) { result.resubmitted_item = diff --git a/shell/common/rasterizer.h b/shell/common/rasterizer.h index 9fb8d03660127..f8d7eee91e28b 100644 --- a/shell/common/rasterizer.h +++ b/shell/common/rasterizer.h @@ -51,10 +51,10 @@ namespace flutter { // The result status of Rasterizer::Draw. This is only used for unit tests. enum class DrawStatus { - // Frame has been successfully rasterized. - kSuccess, - // Failed to rasterize the frame because the rendering context is unavailable. - kContextUnavailable, + // The drawing was done without any specified status. + kDone, + // Failed to rasterize the frame because the Rasterizer is not set up. + kNotSetUp, // Nothing was done, because the call was not on the raster thread. Yielded to // let this frame be serviced on the right thread. kYielded, @@ -64,11 +64,11 @@ enum class DrawStatus { kGpuUnavailable, }; -// The result status of DrawToSurfaceUnsafe. +// The result status of drawing to a view. This is only used for unit tests. enum class DrawSurfaceStatus { - // Frame has been successfully rasterized. + // The layer tree was successfully rasterized. kSuccess, - // Frame should be submitted again. + // The layer tree should be submitted again. // // This can occur on Android when switching the background surface to // FlutterImageView. On Android, the first frame doesn't make the image @@ -80,7 +80,8 @@ enum class DrawSurfaceStatus { kRetry, // Failed to rasterize the frame. kFailed, - // Layer tree was discarded due to LayerTreeDiscardCallback. + // Layer tree was discarded because its size does not match the view size. + // This typically occurs during resizing. kDiscarded, }; @@ -565,16 +566,15 @@ class Rasterizer final : public SnapshotDelegate, private: // The result status of DoDraw, DrawToSurfaces, and DrawToSurfacesUnsafe. enum class DoDrawStatus { - // Frame has been successfully rasterized. - kSuccess, + // The drawing was done without any specified status. + kDone, // Frame has been successfully rasterized, but there are additional items // in the pipeline waiting to be consumed. This is currently only used when // thread configuration change occurs. kEnqueuePipeline, - // Failed to rasterize the frame because the rendering context is - // unavailable. - kContextUnavailable, - // Layer tree was discarded due to inability to access the GPU. + // Failed to rasterize the frame because the Rasterizer is not set up. + kNotSetUp, + // Nothing was done, because GPU was unavailable. kGpuUnavailable, }; @@ -586,7 +586,7 @@ class Rasterizer final : public SnapshotDelegate, // configuration, in which case the resubmitted task will be inserted to the // front of the pipeline. struct DoDrawResult { - DoDrawStatus status = DoDrawStatus::kSuccess; + DoDrawStatus status = DoDrawStatus::kDone; std::unique_ptr resubmitted_item; }; @@ -654,15 +654,23 @@ class Rasterizer final : public SnapshotDelegate, DoDrawResult DrawToSurfaces(FrameTimingsRecorder& frame_timings_recorder, std::list tasks); + // Draws the specified layer trees to views, assuming we have access to the + // GPU. + // + // If any layer trees need resubmitting, this method returns the frame item to + // be resubmitted. Otherwise, it returns nullptr. + // // Unsafe because it assumes we have access to the GPU which isn't the case // when iOS is backgrounded, for example. - // \see Rasterizer::DrawToSurfaces // // This method pushes the frame timing recorder from build end to raster end. std::unique_ptr DrawToSurfacesUnsafe( FrameTimingsRecorder& frame_timings_recorder, std::list tasks); + // Draws the layer tree to the specified view, assuming we have access to the + // GPU. + // // This method pushes the frame timing recorder from build end to raster end. DrawSurfaceStatus DrawToSurfaceUnsafe( FrameTimingsRecorder& frame_timings_recorder, diff --git a/shell/common/rasterizer_unittests.cc b/shell/common/rasterizer_unittests.cc index 71cea73ed6a6f..e7c663399bf43 100644 --- a/shell/common/rasterizer_unittests.cc +++ b/shell/common/rasterizer_unittests.cc @@ -565,7 +565,7 @@ TEST(RasterizerTest, externalViewEmbedderDoesntEndFrameWhenNotUsedThisFrame) { // Always discard the layer tree. ON_CALL(delegate, ShouldDiscardLayerTree).WillByDefault(Return(true)); DrawStatus status = rasterizer->Draw(pipeline); - EXPECT_EQ(status, DrawStatus::kSuccess); + EXPECT_EQ(status, DrawStatus::kDone); EXPECT_EQ(rasterizer->GetLastDrawStatus(kImplicitViewId), DrawSurfaceStatus::kDiscarded); latch.Signal(); @@ -729,7 +729,7 @@ TEST( EXPECT_TRUE(result.success); ON_CALL(delegate, ShouldDiscardLayerTree).WillByDefault(Return(false)); DrawStatus status = rasterizer->Draw(pipeline); - EXPECT_EQ(status, DrawStatus::kSuccess); + EXPECT_EQ(status, DrawStatus::kDone); latch.Signal(); }); latch.Wait(); @@ -788,7 +788,7 @@ TEST( EXPECT_TRUE(result.success); ON_CALL(delegate, ShouldDiscardLayerTree).WillByDefault(Return(false)); DrawStatus status = rasterizer->Draw(pipeline); - EXPECT_EQ(status, DrawStatus::kSuccess); + EXPECT_EQ(status, DrawStatus::kDone); latch.Signal(); }); latch.Wait(); @@ -903,7 +903,7 @@ TEST( EXPECT_TRUE(result.success); ON_CALL(delegate, ShouldDiscardLayerTree).WillByDefault(Return(false)); DrawStatus status = rasterizer->Draw(pipeline); - EXPECT_EQ(status, DrawStatus::kSuccess); + EXPECT_EQ(status, DrawStatus::kDone); EXPECT_EQ(rasterizer->GetLastDrawStatus(kImplicitViewId), DrawSurfaceStatus::kFailed); latch.Signal(); From 2fd98461d14af26b78f464b661092ff4d019b78e Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Mon, 11 Sep 2023 12:27:15 -0700 Subject: [PATCH 28/48] Move EVE::BeginFrame to outside --- shell/common/rasterizer.cc | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index ef52db0349e6d..a6f47f0528dcc 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -557,10 +557,19 @@ std::unique_ptr Rasterizer::DrawToSurfacesUnsafe( FML_CHECK(tasks.size() == 1u); auto& task = tasks.front(); FML_DCHECK(task.view_id == kFlutterImplicitViewId); + int64_t view_id = kFlutterImplicitViewId; std::unique_ptr layer_tree = std::move(task.layer_tree); float device_pixel_ratio = task.device_pixel_ratio; + if (external_view_embedder_) { + FML_DCHECK(!external_view_embedder_->GetUsedThisFrame()); + external_view_embedder_->SetUsedThisFrame(true); + external_view_embedder_->BeginFrame( + layer_tree->frame_size(), surface_->GetContext(), device_pixel_ratio, + raster_thread_merger_); + } + DrawSurfaceStatus status = DrawToSurfaceUnsafe( frame_timings_recorder, view_id, *layer_tree, device_pixel_ratio); @@ -601,11 +610,7 @@ DrawSurfaceStatus Rasterizer::DrawToSurfaceUnsafe( DlCanvas* embedder_root_canvas = nullptr; if (external_view_embedder_) { - FML_DCHECK(!external_view_embedder_->GetUsedThisFrame()); - external_view_embedder_->SetUsedThisFrame(true); - external_view_embedder_->BeginFrame( - layer_tree.frame_size(), surface_->GetContext(), device_pixel_ratio, - raster_thread_merger_); + FML_DCHECK(external_view_embedder_->GetUsedThisFrame()); embedder_root_canvas = external_view_embedder_->GetRootCanvas(); } From 1a539776dc3bf3cf1c5b52e202fb132850d4f9e5 Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Tue, 12 Sep 2023 15:59:48 -0700 Subject: [PATCH 29/48] Fix EVE::beginframe error --- shell/common/rasterizer.cc | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index f9ed50d735962..befb72fa99c38 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -558,15 +558,6 @@ std::unique_ptr Rasterizer::DrawToSurfacesUnsafe( auto& task = tasks.front(); FML_DCHECK(task.view_id == kFlutterImplicitViewId); - if (external_view_embedder_) { - FML_DCHECK(!external_view_embedder_->GetUsedThisFrame()); - external_view_embedder_->SetUsedThisFrame(true); - external_view_embedder_->BeginFrame( - // TODO(dkwingsmt): Add the frame size and DPR for all layer trees. - task.layer_tree->frame_size(), surface_->GetContext(), - task.device_pixel_ratio, raster_thread_merger_); - } - std::optional presentation_time = std::nullopt; // TODO (https://github.com/flutter/flutter/issues/105596): this can be in // the past and might need to get snapped to future as this frame could @@ -631,7 +622,13 @@ DrawSurfaceStatus Rasterizer::DrawToSurfaceUnsafe( DlCanvas* embedder_root_canvas = nullptr; if (external_view_embedder_) { + external_view_embedder_->SetUsedThisFrame(true); + external_view_embedder_->BeginFrame( + // TODO(dkwingsmt): Add view ID here. + layer_tree.frame_size(), surface_->GetContext(), device_pixel_ratio, + raster_thread_merger_); FML_DCHECK(external_view_embedder_->GetUsedThisFrame()); + // TODO(dkwingsmt): Add view ID here. embedder_root_canvas = external_view_embedder_->GetRootCanvas(); } From ef78cfd3e4186db21f4600bd44b978977abadc5b Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Wed, 13 Sep 2023 21:44:09 -0700 Subject: [PATCH 30/48] repeated rasters recorders --- flow/frame_timings.cc | 20 ++++++++++---------- flow/frame_timings.h | 19 ++++++++++++------- shell/common/rasterizer.cc | 10 ++++++---- shell/common/rasterizer.h | 1 + 4 files changed, 29 insertions(+), 21 deletions(-) diff --git a/flow/frame_timings.cc b/flow/frame_timings.cc index eed35fd4c755a..76371e23ab2c5 100644 --- a/flow/frame_timings.cc +++ b/flow/frame_timings.cc @@ -165,12 +165,15 @@ fml::Status FrameTimingsRecorder::RecordBuildEndImpl(fml::TimePoint build_end) { fml::Status FrameTimingsRecorder::RecordRasterStartImpl( fml::TimePoint raster_start) { std::scoped_lock state_lock(state_mutex_); - if (state_ != State::kBuildEnd) { + if (state_ != State::kBuildEnd && state_ != State::kRasterEnd) { return fml::Status(fml::StatusCode::kFailedPrecondition, - "Check failed: state_ == State::kBuildEnd."); + "Check failed: state_ == State::kBuildEnd " + "|| state_ == State::kRasterEnd."); } state_ = State::kRasterStart; - raster_start_ = raster_start; + if (state_ == State::kBuildEnd) { + raster_start_ = raster_start; + } return fml::Status(); } @@ -183,13 +186,10 @@ FrameTiming FrameTimingsRecorder::RecordRasterEnd(const RasterCache* cache) { if (cache) { const RasterCacheMetrics& layer_metrics = cache->layer_metrics(); const RasterCacheMetrics& picture_metrics = cache->picture_metrics(); - layer_cache_count_ = layer_metrics.total_count(); - layer_cache_bytes_ = layer_metrics.total_bytes(); - picture_cache_count_ = picture_metrics.total_count(); - picture_cache_bytes_ = picture_metrics.total_bytes(); - } else { - layer_cache_count_ = layer_cache_bytes_ = picture_cache_count_ = - picture_cache_bytes_ = 0; + layer_cache_count_ += layer_metrics.total_count(); + layer_cache_bytes_ += layer_metrics.total_bytes(); + picture_cache_count_ += picture_metrics.total_count(); + picture_cache_bytes_ += picture_metrics.total_bytes(); } timing_.Set(FrameTiming::kVsyncStart, vsync_start_); timing_.Set(FrameTiming::kBuildStart, build_start_); diff --git a/flow/frame_timings.h b/flow/frame_timings.h index e477a80b8f955..e00d52efab2d1 100644 --- a/flow/frame_timings.h +++ b/flow/frame_timings.h @@ -98,13 +98,18 @@ class FrameTimingsRecorder { /// Records a raster start event. void RecordRasterStart(fml::TimePoint raster_start); - /// Clones the recorder until (and including) the specified state. - std::unique_ptr CloneUntil(State state); - /// Records a raster end event, and builds a `FrameTiming` that summarizes all /// the events. This summary is sent to the framework. + /// + /// RecordRasterStart-RecordRasterEnd pairs can be called for as many times as + /// needed, each time per layer tree. Subsequent pairs will not refresh raster + /// start time, but will refresh raster end time, and accumulate cache + /// metrics. FrameTiming RecordRasterEnd(const RasterCache* cache = nullptr); + /// Clones the recorder until (and including) the specified state. + std::unique_ptr CloneUntil(State state); + /// Returns the frame number. Frame number is unique per frame and a frame /// built earlier will have a frame number less than a frame that has been /// built at a later point of time. @@ -143,10 +148,10 @@ class FrameTimingsRecorder { fml::TimePoint raster_end_; fml::TimePoint raster_end_wall_time_; - size_t layer_cache_count_; - size_t layer_cache_bytes_; - size_t picture_cache_count_; - size_t picture_cache_bytes_; + size_t layer_cache_count_ = 0; + size_t layer_cache_bytes_ = 0; + size_t picture_cache_count_ = 0; + size_t picture_cache_bytes_ = 0; // Set when `RecordRasterEnd` is called. Cannot be reset once set. FrameTiming timing_; diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index befb72fa99c38..6970f2b4318a7 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -572,15 +572,14 @@ std::unique_ptr Rasterizer::DrawToSurfacesUnsafe( compositor_context_->ui_time().SetLapTime( frame_timings_recorder.GetBuildDuration()); - frame_timings_recorder.RecordRasterStart(fml::TimePoint::Now()); int64_t view_id = kFlutterImplicitViewId; std::unique_ptr layer_tree = std::move(task.layer_tree); float device_pixel_ratio = task.device_pixel_ratio; - DrawSurfaceStatus status = DrawToSurfaceUnsafe( - view_id, *layer_tree, device_pixel_ratio, presentation_time); - + DrawSurfaceStatus status = + DrawToSurfaceUnsafe(view_id, *layer_tree, device_pixel_ratio, + frame_timings_recorder, presentation_time); last_draw_status_ = status; std::unique_ptr resubmitted_item; @@ -613,6 +612,7 @@ DrawSurfaceStatus Rasterizer::DrawToSurfaceUnsafe( int64_t view_id, flutter::LayerTree& layer_tree, float device_pixel_ratio, + FrameTimingsRecorder& frame_timings_recorder, std::optional presentation_time) { FML_DCHECK(surface_); @@ -632,6 +632,8 @@ DrawSurfaceStatus Rasterizer::DrawToSurfaceUnsafe( embedder_root_canvas = external_view_embedder_->GetRootCanvas(); } + frame_timings_recorder.RecordRasterStart(fml::TimePoint::Now()); + // On Android, the external view embedder deletes surfaces in `BeginFrame`. // // Deleting a surface also clears the GL context. Therefore, acquire the diff --git a/shell/common/rasterizer.h b/shell/common/rasterizer.h index 07304b39ba3c7..7b8ce36e772d4 100644 --- a/shell/common/rasterizer.h +++ b/shell/common/rasterizer.h @@ -677,6 +677,7 @@ class Rasterizer final : public SnapshotDelegate, int64_t view_id, flutter::LayerTree& layer_tree, float device_pixel_ratio, + FrameTimingsRecorder& frame_timings_recorder, std::optional presentation_time); void FireNextFrameCallbackIfPresent(); From 0a210b8712f57d28353e8a33a2bbb0ca692588b6 Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Wed, 13 Sep 2023 22:50:41 -0700 Subject: [PATCH 31/48] Fix tests --- flow/frame_timings.cc | 2 +- shell/common/rasterizer.cc | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/flow/frame_timings.cc b/flow/frame_timings.cc index 76371e23ab2c5..2f79252c8f32d 100644 --- a/flow/frame_timings.cc +++ b/flow/frame_timings.cc @@ -170,10 +170,10 @@ fml::Status FrameTimingsRecorder::RecordRasterStartImpl( "Check failed: state_ == State::kBuildEnd " "|| state_ == State::kRasterEnd."); } - state_ = State::kRasterStart; if (state_ == State::kBuildEnd) { raster_start_ = raster_start; } + state_ = State::kRasterStart; return fml::Status(); } diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index 6970f2b4318a7..3023fb04cadaa 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -617,6 +617,7 @@ DrawSurfaceStatus Rasterizer::DrawToSurfaceUnsafe( FML_DCHECK(surface_); if (delegate_.ShouldDiscardLayerTree(view_id, layer_tree)) { + frame_timings_recorder.RecordRasterStart(fml::TimePoint::Now()); return DrawSurfaceStatus::kDiscarded; } From bae59ecd1bb59876c7bb795d00cfeb1153efbb2a Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Wed, 13 Sep 2023 22:56:08 -0700 Subject: [PATCH 32/48] Make a loop --- shell/common/rasterizer.cc | 56 ++++++++++++++++++++------------------ shell/common/rasterizer.h | 3 +- 2 files changed, 30 insertions(+), 29 deletions(-) diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index 3023fb04cadaa..5bce74b8e89cb 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -555,8 +555,7 @@ std::unique_ptr Rasterizer::DrawToSurfacesUnsafe( // and that view must be the implicit view. Properly support multi-view // in the future. FML_CHECK(tasks.size() == 1u); - auto& task = tasks.front(); - FML_DCHECK(task.view_id == kFlutterImplicitViewId); + FML_DCHECK(tasks.front().view_id == kFlutterImplicitViewId); std::optional presentation_time = std::nullopt; // TODO (https://github.com/flutter/flutter/issues/105596): this can be in @@ -573,38 +572,41 @@ std::unique_ptr Rasterizer::DrawToSurfacesUnsafe( compositor_context_->ui_time().SetLapTime( frame_timings_recorder.GetBuildDuration()); - int64_t view_id = kFlutterImplicitViewId; - std::unique_ptr layer_tree = std::move(task.layer_tree); - float device_pixel_ratio = task.device_pixel_ratio; - - DrawSurfaceStatus status = - DrawToSurfaceUnsafe(view_id, *layer_tree, device_pixel_ratio, - frame_timings_recorder, presentation_time); - last_draw_status_ = status; - - std::unique_ptr resubmitted_item; - if (status == DrawSurfaceStatus::kSuccess) { - last_successful_tasks_.insert_or_assign( - view_id, - LayerTreeTask(view_id, std::move(layer_tree), device_pixel_ratio)); - } else if (status == DrawSurfaceStatus::kRetry) { - std::list resubmitted_tasks; - resubmitted_tasks.emplace_back(view_id, std::move(layer_tree), - device_pixel_ratio); - resubmitted_item = std::make_unique( - std::move(resubmitted_tasks), - frame_timings_recorder.CloneUntil( - FrameTimingsRecorder::State::kBuildEnd)); + std::list resubmitted_tasks; + for (LayerTreeTask& task : tasks) { + int64_t view_id = task.view_id; + std::unique_ptr layer_tree = std::move(task.layer_tree); + float device_pixel_ratio = task.device_pixel_ratio; + + DrawSurfaceStatus status = + DrawToSurfaceUnsafe(view_id, *layer_tree, device_pixel_ratio, + frame_timings_recorder, presentation_time); + frame_timings_recorder.RecordRasterEnd(&compositor_context_->raster_cache()); + + last_draw_status_ = status; + if (status == DrawSurfaceStatus::kSuccess) { + last_successful_tasks_.insert_or_assign( + view_id, + LayerTreeTask(view_id, std::move(layer_tree), device_pixel_ratio)); + } else if (status == DrawSurfaceStatus::kRetry) { + resubmitted_tasks.emplace_back(view_id, std::move(layer_tree), + device_pixel_ratio); + } } - - frame_timings_recorder.RecordRasterEnd(&compositor_context_->raster_cache()); FireNextFrameCallbackIfPresent(); if (surface_->GetContext()) { surface_->GetContext()->performDeferredCleanup(kSkiaCleanupExpiration); } - return resubmitted_item; + if (resubmitted_tasks.empty()) { + return nullptr; + } else { + return std::make_unique( + std::move(resubmitted_tasks), + frame_timings_recorder.CloneUntil( + FrameTimingsRecorder::State::kBuildEnd)); + } } /// \see Rasterizer::DrawToSurfaces diff --git a/shell/common/rasterizer.h b/shell/common/rasterizer.h index 7b8ce36e772d4..0350158e6b498 100644 --- a/shell/common/rasterizer.h +++ b/shell/common/rasterizer.h @@ -671,8 +671,7 @@ class Rasterizer final : public SnapshotDelegate, // Draws the layer tree to the specified view, assuming we have access to the // GPU. // - // This method is not affiliated with the frame timing recorder, but should be - // included within the raster phase. + // This method pushes the frame timing recorder from build end to raster start. DrawSurfaceStatus DrawToSurfaceUnsafe( int64_t view_id, flutter::LayerTree& layer_tree, From 0f0a62820bd934449c68f8a7f88489348a4b7aeb Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Wed, 13 Sep 2023 23:53:59 -0700 Subject: [PATCH 33/48] Fix timing test --- flow/frame_timings_recorder_unittests.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flow/frame_timings_recorder_unittests.cc b/flow/frame_timings_recorder_unittests.cc index c7fa7390a4c6e..d5181844775b2 100644 --- a/flow/frame_timings_recorder_unittests.cc +++ b/flow/frame_timings_recorder_unittests.cc @@ -144,7 +144,7 @@ TEST(FrameTimingsRecorderTest, ThrowWhenRecordRasterBeforeBuildEnd) { const auto raster_start = fml::TimePoint::Now(); fml::Status status = recorder->RecordRasterStartImpl(raster_start); EXPECT_FALSE(status.ok()); - EXPECT_EQ(status.message(), "Check failed: state_ == State::kBuildEnd."); + EXPECT_EQ(status.message(), "Check failed: state_ == State::kBuildEnd || state_ == State::kRasterEnd."); } #endif From 9b74f4f41620941c0ef9f407208aefd3aacd8d4d Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Wed, 13 Sep 2023 23:54:28 -0700 Subject: [PATCH 34/48] Fix timing test --- flow/frame_timings_recorder_unittests.cc | 4 +++- shell/common/rasterizer.cc | 5 +++-- shell/common/rasterizer.h | 3 ++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/flow/frame_timings_recorder_unittests.cc b/flow/frame_timings_recorder_unittests.cc index d5181844775b2..49833b2de0f17 100644 --- a/flow/frame_timings_recorder_unittests.cc +++ b/flow/frame_timings_recorder_unittests.cc @@ -144,7 +144,9 @@ TEST(FrameTimingsRecorderTest, ThrowWhenRecordRasterBeforeBuildEnd) { const auto raster_start = fml::TimePoint::Now(); fml::Status status = recorder->RecordRasterStartImpl(raster_start); EXPECT_FALSE(status.ok()); - EXPECT_EQ(status.message(), "Check failed: state_ == State::kBuildEnd || state_ == State::kRasterEnd."); + EXPECT_EQ(status.message(), + "Check failed: state_ == State::kBuildEnd " + "|| state_ == State::kRasterEnd."); } #endif diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index 5bce74b8e89cb..17c659aab8988 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -581,7 +581,8 @@ std::unique_ptr Rasterizer::DrawToSurfacesUnsafe( DrawSurfaceStatus status = DrawToSurfaceUnsafe(view_id, *layer_tree, device_pixel_ratio, frame_timings_recorder, presentation_time); - frame_timings_recorder.RecordRasterEnd(&compositor_context_->raster_cache()); + frame_timings_recorder.RecordRasterEnd( + &compositor_context_->raster_cache()); last_draw_status_ = status; if (status == DrawSurfaceStatus::kSuccess) { @@ -590,7 +591,7 @@ std::unique_ptr Rasterizer::DrawToSurfacesUnsafe( LayerTreeTask(view_id, std::move(layer_tree), device_pixel_ratio)); } else if (status == DrawSurfaceStatus::kRetry) { resubmitted_tasks.emplace_back(view_id, std::move(layer_tree), - device_pixel_ratio); + device_pixel_ratio); } } FireNextFrameCallbackIfPresent(); diff --git a/shell/common/rasterizer.h b/shell/common/rasterizer.h index 0350158e6b498..dbd7afcba7397 100644 --- a/shell/common/rasterizer.h +++ b/shell/common/rasterizer.h @@ -671,7 +671,8 @@ class Rasterizer final : public SnapshotDelegate, // Draws the layer tree to the specified view, assuming we have access to the // GPU. // - // This method pushes the frame timing recorder from build end to raster start. + // This method pushes the frame timing recorder from build end to raster + // start. DrawSurfaceStatus DrawToSurfaceUnsafe( int64_t view_id, flutter::LayerTree& layer_tree, From 0f539e14bd94130a2bd396591438666f75bd8421 Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Thu, 14 Sep 2023 14:11:18 -0700 Subject: [PATCH 35/48] Filter discarded trees beforehand --- flow/frame_timings.cc | 20 ++++---- flow/frame_timings.h | 19 +++----- flow/frame_timings_recorder_unittests.cc | 4 +- shell/common/rasterizer.cc | 61 ++++++++++++++---------- shell/common/rasterizer.h | 5 +- 5 files changed, 56 insertions(+), 53 deletions(-) diff --git a/flow/frame_timings.cc b/flow/frame_timings.cc index 2f79252c8f32d..eed35fd4c755a 100644 --- a/flow/frame_timings.cc +++ b/flow/frame_timings.cc @@ -165,15 +165,12 @@ fml::Status FrameTimingsRecorder::RecordBuildEndImpl(fml::TimePoint build_end) { fml::Status FrameTimingsRecorder::RecordRasterStartImpl( fml::TimePoint raster_start) { std::scoped_lock state_lock(state_mutex_); - if (state_ != State::kBuildEnd && state_ != State::kRasterEnd) { + if (state_ != State::kBuildEnd) { return fml::Status(fml::StatusCode::kFailedPrecondition, - "Check failed: state_ == State::kBuildEnd " - "|| state_ == State::kRasterEnd."); - } - if (state_ == State::kBuildEnd) { - raster_start_ = raster_start; + "Check failed: state_ == State::kBuildEnd."); } state_ = State::kRasterStart; + raster_start_ = raster_start; return fml::Status(); } @@ -186,10 +183,13 @@ FrameTiming FrameTimingsRecorder::RecordRasterEnd(const RasterCache* cache) { if (cache) { const RasterCacheMetrics& layer_metrics = cache->layer_metrics(); const RasterCacheMetrics& picture_metrics = cache->picture_metrics(); - layer_cache_count_ += layer_metrics.total_count(); - layer_cache_bytes_ += layer_metrics.total_bytes(); - picture_cache_count_ += picture_metrics.total_count(); - picture_cache_bytes_ += picture_metrics.total_bytes(); + layer_cache_count_ = layer_metrics.total_count(); + layer_cache_bytes_ = layer_metrics.total_bytes(); + picture_cache_count_ = picture_metrics.total_count(); + picture_cache_bytes_ = picture_metrics.total_bytes(); + } else { + layer_cache_count_ = layer_cache_bytes_ = picture_cache_count_ = + picture_cache_bytes_ = 0; } timing_.Set(FrameTiming::kVsyncStart, vsync_start_); timing_.Set(FrameTiming::kBuildStart, build_start_); diff --git a/flow/frame_timings.h b/flow/frame_timings.h index e00d52efab2d1..e477a80b8f955 100644 --- a/flow/frame_timings.h +++ b/flow/frame_timings.h @@ -98,18 +98,13 @@ class FrameTimingsRecorder { /// Records a raster start event. void RecordRasterStart(fml::TimePoint raster_start); + /// Clones the recorder until (and including) the specified state. + std::unique_ptr CloneUntil(State state); + /// Records a raster end event, and builds a `FrameTiming` that summarizes all /// the events. This summary is sent to the framework. - /// - /// RecordRasterStart-RecordRasterEnd pairs can be called for as many times as - /// needed, each time per layer tree. Subsequent pairs will not refresh raster - /// start time, but will refresh raster end time, and accumulate cache - /// metrics. FrameTiming RecordRasterEnd(const RasterCache* cache = nullptr); - /// Clones the recorder until (and including) the specified state. - std::unique_ptr CloneUntil(State state); - /// Returns the frame number. Frame number is unique per frame and a frame /// built earlier will have a frame number less than a frame that has been /// built at a later point of time. @@ -148,10 +143,10 @@ class FrameTimingsRecorder { fml::TimePoint raster_end_; fml::TimePoint raster_end_wall_time_; - size_t layer_cache_count_ = 0; - size_t layer_cache_bytes_ = 0; - size_t picture_cache_count_ = 0; - size_t picture_cache_bytes_ = 0; + size_t layer_cache_count_; + size_t layer_cache_bytes_; + size_t picture_cache_count_; + size_t picture_cache_bytes_; // Set when `RecordRasterEnd` is called. Cannot be reset once set. FrameTiming timing_; diff --git a/flow/frame_timings_recorder_unittests.cc b/flow/frame_timings_recorder_unittests.cc index 49833b2de0f17..c7fa7390a4c6e 100644 --- a/flow/frame_timings_recorder_unittests.cc +++ b/flow/frame_timings_recorder_unittests.cc @@ -144,9 +144,7 @@ TEST(FrameTimingsRecorderTest, ThrowWhenRecordRasterBeforeBuildEnd) { const auto raster_start = fml::TimePoint::Now(); fml::Status status = recorder->RecordRasterStartImpl(raster_start); EXPECT_FALSE(status.ok()); - EXPECT_EQ(status.message(), - "Check failed: state_ == State::kBuildEnd " - "|| state_ == State::kRasterEnd."); + EXPECT_EQ(status.message(), "Check failed: state_ == State::kBuildEnd."); } #endif diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index 17c659aab8988..9d382328e334d 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -227,10 +227,6 @@ DrawStatus Rasterizer::Draw( DoDrawResult draw_result; LayerTreePipeline::Consumer consumer = [&draw_result, this]( std::unique_ptr item) { - if (item->tasks.empty()) { - draw_result.status = DoDrawStatus::kDone; - return; - } draw_result = DoDraw(std::move(item->frame_timings_recorder), std::move(item->tasks)); }; @@ -557,6 +553,36 @@ std::unique_ptr Rasterizer::DrawToSurfacesUnsafe( FML_CHECK(tasks.size() == 1u); FML_DCHECK(tasks.front().view_id == kFlutterImplicitViewId); + compositor_context_->ui_time().SetLapTime( + frame_timings_recorder.GetBuildDuration()); + + // First traverse: Filter out discarded trees + auto task_iter = tasks.begin(); + while (task_iter != tasks.end()) { + if (delegate_.ShouldDiscardLayerTree(task_iter->view_id, + *task_iter->layer_tree)) { + // TODO(dkwingsmt): multi-view statuses + last_draw_status_ = DrawSurfaceStatus::kDiscarded; + task_iter = tasks.erase(task_iter); + } else { + ++task_iter; + } + } + if (tasks.empty()) { + frame_timings_recorder.RecordRasterStart(fml::TimePoint::Now()); + frame_timings_recorder.RecordRasterEnd(); + return nullptr; + } + + if (external_view_embedder_) { + FML_DCHECK(!external_view_embedder_->GetUsedThisFrame()); + external_view_embedder_->SetUsedThisFrame(true); + external_view_embedder_->BeginFrame( + // TODO(dkwingsmt): Add all views here. + tasks.front().layer_tree->frame_size(), surface_->GetContext(), + tasks.front().device_pixel_ratio, raster_thread_merger_); + } + std::optional presentation_time = std::nullopt; // TODO (https://github.com/flutter/flutter/issues/105596): this can be in // the past and might need to get snapped to future as this frame could @@ -569,20 +595,17 @@ std::unique_ptr Rasterizer::DrawToSurfacesUnsafe( } } - compositor_context_->ui_time().SetLapTime( - frame_timings_recorder.GetBuildDuration()); + frame_timings_recorder.RecordRasterStart(fml::TimePoint::Now()); + // Second traverse: draw all layer trees. std::list resubmitted_tasks; for (LayerTreeTask& task : tasks) { int64_t view_id = task.view_id; std::unique_ptr layer_tree = std::move(task.layer_tree); float device_pixel_ratio = task.device_pixel_ratio; - DrawSurfaceStatus status = - DrawToSurfaceUnsafe(view_id, *layer_tree, device_pixel_ratio, - frame_timings_recorder, presentation_time); - frame_timings_recorder.RecordRasterEnd( - &compositor_context_->raster_cache()); + DrawSurfaceStatus status = DrawToSurfaceUnsafe( + view_id, *layer_tree, device_pixel_ratio, presentation_time); last_draw_status_ = status; if (status == DrawSurfaceStatus::kSuccess) { @@ -594,6 +617,8 @@ std::unique_ptr Rasterizer::DrawToSurfacesUnsafe( device_pixel_ratio); } } + // TODO(dkwingsmt): Pass in all raster caches + frame_timings_recorder.RecordRasterEnd(&compositor_context_->raster_cache()); FireNextFrameCallbackIfPresent(); if (surface_->GetContext()) { @@ -615,29 +640,15 @@ DrawSurfaceStatus Rasterizer::DrawToSurfaceUnsafe( int64_t view_id, flutter::LayerTree& layer_tree, float device_pixel_ratio, - FrameTimingsRecorder& frame_timings_recorder, std::optional presentation_time) { FML_DCHECK(surface_); - if (delegate_.ShouldDiscardLayerTree(view_id, layer_tree)) { - frame_timings_recorder.RecordRasterStart(fml::TimePoint::Now()); - return DrawSurfaceStatus::kDiscarded; - } - DlCanvas* embedder_root_canvas = nullptr; if (external_view_embedder_) { - external_view_embedder_->SetUsedThisFrame(true); - external_view_embedder_->BeginFrame( - // TODO(dkwingsmt): Add view ID here. - layer_tree.frame_size(), surface_->GetContext(), device_pixel_ratio, - raster_thread_merger_); - FML_DCHECK(external_view_embedder_->GetUsedThisFrame()); // TODO(dkwingsmt): Add view ID here. embedder_root_canvas = external_view_embedder_->GetRootCanvas(); } - frame_timings_recorder.RecordRasterStart(fml::TimePoint::Now()); - // On Android, the external view embedder deletes surfaces in `BeginFrame`. // // Deleting a surface also clears the GL context. Therefore, acquire the diff --git a/shell/common/rasterizer.h b/shell/common/rasterizer.h index dbd7afcba7397..b888fb887cc65 100644 --- a/shell/common/rasterizer.h +++ b/shell/common/rasterizer.h @@ -671,13 +671,12 @@ class Rasterizer final : public SnapshotDelegate, // Draws the layer tree to the specified view, assuming we have access to the // GPU. // - // This method pushes the frame timing recorder from build end to raster - // start. + // This method is not affiliated with the frame timing recorder, but should be + // included between the RasterStart and RasterEnd. DrawSurfaceStatus DrawToSurfaceUnsafe( int64_t view_id, flutter::LayerTree& layer_tree, float device_pixel_ratio, - FrameTimingsRecorder& frame_timings_recorder, std::optional presentation_time); void FireNextFrameCallbackIfPresent(); From a5d895a262c0adff84edd081ec79f5e0e2d5ba82 Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Thu, 14 Sep 2023 14:20:55 -0700 Subject: [PATCH 36/48] Multiview last draw status --- shell/common/rasterizer.cc | 13 +++++++++---- shell/common/rasterizer.h | 4 ++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index 9d382328e334d..3a48ce90c7328 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -135,7 +135,12 @@ bool Rasterizer::IsTornDown() { std::optional Rasterizer::GetLastDrawStatus( int64_t view_id) { - return last_draw_status_; + auto found = last_draw_statuses_.find(view_id); + if (found != last_draw_statuses_.end()) { + return found->second; + } else { + return std::optional(); + } } void Rasterizer::EnableThreadMergerIfNeeded() { @@ -171,6 +176,7 @@ void Rasterizer::NotifyLowMemoryWarning() const { void Rasterizer::CollectView(int64_t view_id) { last_successful_tasks_.erase(view_id); + last_draw_statuses_.erase(view_id); } std::shared_ptr Rasterizer::GetTextureRegistry() { @@ -561,8 +567,7 @@ std::unique_ptr Rasterizer::DrawToSurfacesUnsafe( while (task_iter != tasks.end()) { if (delegate_.ShouldDiscardLayerTree(task_iter->view_id, *task_iter->layer_tree)) { - // TODO(dkwingsmt): multi-view statuses - last_draw_status_ = DrawSurfaceStatus::kDiscarded; + last_draw_statuses_[task_iter->view_id] = DrawSurfaceStatus::kDiscarded; task_iter = tasks.erase(task_iter); } else { ++task_iter; @@ -607,7 +612,7 @@ std::unique_ptr Rasterizer::DrawToSurfacesUnsafe( DrawSurfaceStatus status = DrawToSurfaceUnsafe( view_id, *layer_tree, device_pixel_ratio, presentation_time); - last_draw_status_ = status; + last_draw_statuses_[view_id] = status; if (status == DrawSurfaceStatus::kSuccess) { last_successful_tasks_.insert_or_assign( view_id, diff --git a/shell/common/rasterizer.h b/shell/common/rasterizer.h index b888fb887cc65..5405a6cc2caf5 100644 --- a/shell/common/rasterizer.h +++ b/shell/common/rasterizer.h @@ -691,7 +691,9 @@ class Rasterizer final : public SnapshotDelegate, std::unique_ptr surface_; std::unique_ptr snapshot_surface_producer_; std::unique_ptr compositor_context_; + // TODO(dkwingsmt): Probably merge them. std::unordered_map last_successful_tasks_; + std::unordered_map last_draw_statuses_; fml::closure next_frame_callback_; bool user_override_resource_cache_bytes_; std::optional max_cache_bytes_; @@ -699,8 +701,6 @@ class Rasterizer final : public SnapshotDelegate, std::shared_ptr external_view_embedder_; std::unique_ptr snapshot_controller_; - DrawSurfaceStatus last_draw_status_; - // WeakPtrFactory must be the last member. fml::TaskRunnerAffineWeakPtrFactory weak_factory_; FML_DISALLOW_COPY_AND_ASSIGN(Rasterizer); From a19f56bc629230005a1b62f81db18cd5c259f5d9 Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Thu, 14 Sep 2023 14:34:51 -0700 Subject: [PATCH 37/48] Check task empty in DoDraw --- shell/common/rasterizer.cc | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index 3a48ce90c7328..35d1bf19d3dd2 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -428,10 +428,12 @@ Rasterizer::DoDrawResult Rasterizer::DoDraw( .GetRasterTaskRunner() ->RunsTasksOnCurrentThread()); + + if (tasks.empty()) { + return DoDrawResult{DoDrawStatus::kDone}; + } if (!surface_) { - return DoDrawResult{ - .status = DoDrawStatus::kNotSetUp, - }; + return DoDrawResult{DoDrawStatus::kNotSetUp}; } PersistentCache* persistent_cache = PersistentCache::GetCacheForProcess(); @@ -441,9 +443,7 @@ Rasterizer::DoDrawResult Rasterizer::DoDraw( DrawToSurfaces(*frame_timings_recorder, std::move(tasks)); FML_DCHECK(result.status != DoDrawStatus::kEnqueuePipeline); if (result.status == DoDrawStatus::kGpuUnavailable) { - return DoDrawResult{ - .status = DoDrawStatus::kGpuUnavailable, - }; + return DoDrawResult{DoDrawStatus::kGpuUnavailable}; } if (persistent_cache->IsDumpingSkp() && From e3be81cbebf4b7bb9c3dce6fa81dbc6c99a356a6 Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Thu, 14 Sep 2023 14:45:12 -0700 Subject: [PATCH 38/48] frame_timings_recorder.AssertInState --- flow/frame_timings.cc | 4 ++++ flow/frame_timings.h | 6 ++++++ shell/common/rasterizer.cc | 8 ++++++-- shell/common/rasterizer.h | 3 +++ 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/flow/frame_timings.cc b/flow/frame_timings.cc index eed35fd4c755a..339374d77b837 100644 --- a/flow/frame_timings.cc +++ b/flow/frame_timings.cc @@ -254,4 +254,8 @@ const char* FrameTimingsRecorder::GetFrameNumberTraceArg() const { return frame_number_trace_arg_val_.c_str(); } +void FrameTimingsRecorder::AssertInState(State state) const { + FML_DCHECK(state_ == state); +} + } // namespace flutter diff --git a/flow/frame_timings.h b/flow/frame_timings.h index e477a80b8f955..06f6f0b53f606 100644 --- a/flow/frame_timings.h +++ b/flow/frame_timings.h @@ -116,6 +116,12 @@ class FrameTimingsRecorder { /// Returns the recorded time from when `RecordRasterEnd` is called. FrameTiming GetRecordedTime() const; + /// Asserts in debug mode that the recorder is current at the specified state. + /// + /// A `GetState` method is not preferred to avoid other logic relying on this + /// state. + void AssertInState(State state) const; + private: FML_FRIEND_TEST(FrameTimingsRecorderTest, ThrowWhenRecordBuildBeforeVsync); FML_FRIEND_TEST(FrameTimingsRecorderTest, diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index 35d1bf19d3dd2..8d95fb5141c55 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -294,10 +294,10 @@ DrawStatus Rasterizer::ToDrawStatus(DoDrawStatus status) { switch (status) { case DoDrawStatus::kEnqueuePipeline: return DrawStatus::kDone; - case DoDrawStatus::kGpuUnavailable: - return DrawStatus::kGpuUnavailable; case DoDrawStatus::kNotSetUp: return DrawStatus::kNotSetUp; + case DoDrawStatus::kGpuUnavailable: + return DrawStatus::kGpuUnavailable; default: FML_CHECK(status == DoDrawStatus::kDone) << "Unrecognized status " << (int)status; @@ -427,6 +427,7 @@ Rasterizer::DoDrawResult Rasterizer::DoDraw( FML_DCHECK(delegate_.GetTaskRunners() .GetRasterTaskRunner() ->RunsTasksOnCurrentThread()); + frame_timings_recorder->AssertInState(FrameTimingsRecorder::State::kBuildEnd); if (tasks.empty()) { @@ -441,6 +442,7 @@ Rasterizer::DoDrawResult Rasterizer::DoDraw( DoDrawResult result = DrawToSurfaces(*frame_timings_recorder, std::move(tasks)); + FML_DCHECK(result.status != DoDrawStatus::kEnqueuePipeline); if (result.status == DoDrawStatus::kGpuUnavailable) { return DoDrawResult{DoDrawStatus::kGpuUnavailable}; @@ -526,6 +528,7 @@ Rasterizer::DoDrawResult Rasterizer::DrawToSurfaces( std::list tasks) { TRACE_EVENT0("flutter", "Rasterizer::DrawToSurfaces"); FML_DCHECK(surface_); + frame_timings_recorder.AssertInState(FrameTimingsRecorder::State::kBuildEnd); DoDrawResult result{ .status = DoDrawStatus::kDone, @@ -546,6 +549,7 @@ Rasterizer::DoDrawResult Rasterizer::DrawToSurfaces( frame_timings_recorder, std::move(tasks)); })); } + frame_timings_recorder.AssertInState(FrameTimingsRecorder::State::kRasterEnd); return result; } diff --git a/shell/common/rasterizer.h b/shell/common/rasterizer.h index 5405a6cc2caf5..733f720f28ae9 100644 --- a/shell/common/rasterizer.h +++ b/shell/common/rasterizer.h @@ -646,6 +646,9 @@ class Rasterizer final : public SnapshotDelegate, GrDirectContext* surface_context, bool compressed); + // This method starts with the frame timing recorder at build end. This + // method might push it to raster end and get the recorded time, or abort in + // the middle and not get the recorded time. DoDrawResult DoDraw( std::unique_ptr frame_timings_recorder, std::list tasks); From 6d62c32edd47ec0c6fce15219f7ce24a51a89010 Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Wed, 20 Sep 2023 14:10:57 -0700 Subject: [PATCH 39/48] Move pipeline def to rasterizer.h --- flow/layers/layer_tree.h | 12 ----------- shell/common/animator.cc | 4 ++-- shell/common/animator.h | 6 +++--- shell/common/animator_unittests.cc | 2 +- shell/common/pipeline.h | 11 ---------- shell/common/rasterizer.cc | 15 ++++++------- shell/common/rasterizer.h | 30 +++++++++++++++++++++++++- shell/common/rasterizer_unittests.cc | 32 ++++++++++++++-------------- shell/common/shell.cc | 6 +++--- shell/common/shell.h | 2 +- 10 files changed, 62 insertions(+), 58 deletions(-) diff --git a/flow/layers/layer_tree.h b/flow/layers/layer_tree.h index 6c374ecf3a228..5f573da2099a0 100644 --- a/flow/layers/layer_tree.h +++ b/flow/layers/layer_tree.h @@ -94,18 +94,6 @@ class LayerTree { FML_DISALLOW_COPY_AND_ASSIGN(LayerTree); }; -struct LayerTreeTask { - LayerTreeTask(int64_t view_id, - std::unique_ptr layer_tree, - float device_pixel_ratio) - : view_id(view_id), - layer_tree(std::move(layer_tree)), - device_pixel_ratio(device_pixel_ratio) {} - int64_t view_id; - std::unique_ptr layer_tree; - float device_pixel_ratio; -}; - } // namespace flutter #endif // FLUTTER_FLOW_LAYERS_LAYER_TREE_H_ diff --git a/shell/common/animator.cc b/shell/common/animator.cc index 967ec6b39b631..1453bb352b4df 100644 --- a/shell/common/animator.cc +++ b/shell/common/animator.cc @@ -29,12 +29,12 @@ Animator::Animator(Delegate& delegate, task_runners_(task_runners), waiter_(std::move(waiter)), #if SHELL_ENABLE_METAL - layer_tree_pipeline_(std::make_shared(2)), + layer_tree_pipeline_(std::make_shared(2)), #else // SHELL_ENABLE_METAL // TODO(dnfield): We should remove this logic and set the pipeline depth // back to 2 in this case. See // https://github.com/flutter/engine/pull/9132 for discussion. - layer_tree_pipeline_(std::make_shared( + layer_tree_pipeline_(std::make_shared( task_runners.GetPlatformTaskRunner() == task_runners.GetRasterTaskRunner() ? 1 diff --git a/shell/common/animator.h b/shell/common/animator.h index 28a3430932a5e..5e78c9fbd9c23 100644 --- a/shell/common/animator.h +++ b/shell/common/animator.h @@ -40,7 +40,7 @@ class Animator final { fml::TimePoint frame_target_time) = 0; virtual void OnAnimatorDraw( - std::shared_ptr pipeline) = 0; + std::shared_ptr pipeline) = 0; virtual void OnAnimatorDrawLastLayerTree( std::unique_ptr frame_timings_recorder) = 0; @@ -102,9 +102,9 @@ class Animator final { std::unique_ptr frame_timings_recorder_; uint64_t frame_request_number_ = 1; fml::TimeDelta dart_frame_deadline_; - std::shared_ptr layer_tree_pipeline_; + std::shared_ptr layer_tree_pipeline_; fml::Semaphore pending_frame_semaphore_; - LayerTreePipeline::ProducerContinuation producer_continuation_; + FramePipeline::ProducerContinuation producer_continuation_; bool regenerate_layer_tree_ = false; bool frame_scheduled_ = false; std::deque trace_flow_ids_; diff --git a/shell/common/animator_unittests.cc b/shell/common/animator_unittests.cc index 459c77b0ec672..60088357f9de4 100644 --- a/shell/common/animator_unittests.cc +++ b/shell/common/animator_unittests.cc @@ -41,7 +41,7 @@ class FakeAnimatorDelegate : public Animator::Delegate { MOCK_METHOD(void, OnAnimatorDraw, - (std::shared_ptr pipeline), + (std::shared_ptr pipeline), (override)); void OnAnimatorDrawLastLayerTree( diff --git a/shell/common/pipeline.h b/shell/common/pipeline.h index b03994e61bd69..72401eec40cd5 100644 --- a/shell/common/pipeline.h +++ b/shell/common/pipeline.h @@ -253,17 +253,6 @@ class Pipeline { FML_DISALLOW_COPY_AND_ASSIGN(Pipeline); }; -struct FrameItem { - FrameItem(std::list tasks, - std::unique_ptr frame_timings_recorder) - : tasks(std::move(tasks)), - frame_timings_recorder(std::move(frame_timings_recorder)) {} - std::list tasks; - std::unique_ptr frame_timings_recorder; -}; - -using LayerTreePipeline = Pipeline; - } // namespace flutter #endif // FLUTTER_SHELL_COMMON_PIPELINE_H_ diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index 8d95fb5141c55..41d79c89cd037 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -219,7 +219,7 @@ void Rasterizer::DrawLastLayerTree( } DrawStatus Rasterizer::Draw( - const std::shared_ptr& pipeline) { + const std::shared_ptr& pipeline) { TRACE_EVENT0("flutter", "GPURasterizer::Draw"); if (raster_thread_merger_ && !raster_thread_merger_->IsOnRasterizingThread()) { @@ -231,11 +231,11 @@ DrawStatus Rasterizer::Draw( ->RunsTasksOnCurrentThread()); DoDrawResult draw_result; - LayerTreePipeline::Consumer consumer = [&draw_result, this]( - std::unique_ptr item) { - draw_result = - DoDraw(std::move(item->frame_timings_recorder), std::move(item->tasks)); - }; + FramePipeline::Consumer consumer = + [&draw_result, this](std::unique_ptr item) { + draw_result = DoDraw(std::move(item->frame_timings_recorder), + std::move(item->layer_tree_tasks)); + }; PipelineConsumeResult consume_result = pipeline->Consume(consumer); if (consume_result == PipelineConsumeResult::NoneAvailable) { @@ -284,7 +284,7 @@ DrawStatus Rasterizer::Draw( bool Rasterizer::ShouldResubmitFrame(const DoDrawResult& result) { if (result.resubmitted_item) { - FML_CHECK(!result.resubmitted_item->tasks.empty()); + FML_CHECK(!result.resubmitted_item->layer_tree_tasks.empty()); return true; } return false; @@ -429,7 +429,6 @@ Rasterizer::DoDrawResult Rasterizer::DoDraw( ->RunsTasksOnCurrentThread()); frame_timings_recorder->AssertInState(FrameTimingsRecorder::State::kBuildEnd); - if (tasks.empty()) { return DoDrawResult{DoDrawStatus::kDone}; } diff --git a/shell/common/rasterizer.h b/shell/common/rasterizer.h index 733f720f28ae9..e98e70b88568a 100644 --- a/shell/common/rasterizer.h +++ b/shell/common/rasterizer.h @@ -85,6 +85,34 @@ enum class DrawSurfaceStatus { kDiscarded, }; +// The information to draw a layer tree to a specified view. +struct LayerTreeTask { + LayerTreeTask(int64_t view_id, + std::unique_ptr layer_tree, + float device_pixel_ratio) + : view_id(view_id), + layer_tree(std::move(layer_tree)), + device_pixel_ratio(device_pixel_ratio) {} + /// The target view to drawn to. + int64_t view_id; + /// The target layer tree to be drawn. + std::unique_ptr layer_tree; + /// The pixel ratio of the target view. + float device_pixel_ratio; +}; + +// The information to draw to all views of a frame. +struct FrameItem { + FrameItem(std::list tasks, + std::unique_ptr frame_timings_recorder) + : layer_tree_tasks(std::move(tasks)), + frame_timings_recorder(std::move(frame_timings_recorder)) {} + std::list layer_tree_tasks; + std::unique_ptr frame_timings_recorder; +}; + +using FramePipeline = Pipeline; + //------------------------------------------------------------------------------ /// The rasterizer is a component owned by the shell that resides on the raster /// task runner. Each shell owns exactly one instance of a rasterizer. The @@ -324,7 +352,7 @@ class Rasterizer final : public SnapshotDelegate, /// @param[in] pipeline The layer tree pipeline to take the next layer tree /// to render from. /// - DrawStatus Draw(const std::shared_ptr& pipeline); + DrawStatus Draw(const std::shared_ptr& pipeline); //---------------------------------------------------------------------------- /// @brief The type of the screenshot to obtain of the previously diff --git a/shell/common/rasterizer_unittests.cc b/shell/common/rasterizer_unittests.cc index e7c663399bf43..b09d5dda67bcf 100644 --- a/shell/common/rasterizer_unittests.cc +++ b/shell/common/rasterizer_unittests.cc @@ -161,7 +161,7 @@ TEST(RasterizerTest, drawEmptyPipeline) { rasterizer->Setup(std::move(surface)); fml::AutoResetWaitableEvent latch; thread_host.raster_thread->GetTaskRunner()->PostTask([&] { - auto pipeline = std::make_shared(/*depth=*/10); + auto pipeline = std::make_shared(/*depth=*/10); ON_CALL(delegate, ShouldDiscardLayerTree).WillByDefault(Return(false)); rasterizer->Draw(pipeline); latch.Signal(); @@ -223,7 +223,7 @@ TEST(RasterizerTest, rasterizer->Setup(std::move(surface)); fml::AutoResetWaitableEvent latch; thread_host.raster_thread->GetTaskRunner()->PostTask([&] { - auto pipeline = std::make_shared(/*depth=*/10); + auto pipeline = std::make_shared(/*depth=*/10); auto layer_tree = std::make_unique(/*config=*/LayerTree::Config(), /*frame_size=*/SkISize()); @@ -291,7 +291,7 @@ TEST( rasterizer->Setup(std::move(surface)); fml::AutoResetWaitableEvent latch; thread_host.raster_thread->GetTaskRunner()->PostTask([&] { - auto pipeline = std::make_shared(/*depth=*/10); + auto pipeline = std::make_shared(/*depth=*/10); auto layer_tree = std::make_unique( /*config=*/LayerTree::Config(), /*frame_size=*/SkISize()); auto layer_tree_item = std::make_unique( @@ -364,7 +364,7 @@ TEST( rasterizer->Setup(std::move(surface)); - auto pipeline = std::make_shared(/*depth=*/10); + auto pipeline = std::make_shared(/*depth=*/10); auto layer_tree = std::make_unique(/*config=*/LayerTree::Config(), /*frame_size=*/SkISize()); auto layer_tree_item = std::make_unique( @@ -440,7 +440,7 @@ TEST(RasterizerTest, rasterizer->Setup(std::move(surface)); - auto pipeline = std::make_shared(/*depth=*/10); + auto pipeline = std::make_shared(/*depth=*/10); auto layer_tree = std::make_unique(/*config=*/LayerTree::Config(), /*frame_size=*/SkISize()); auto layer_tree_item = std::make_unique( @@ -491,7 +491,7 @@ TEST(RasterizerTest, externalViewEmbedderDoesntEndFrameWhenNoSurfaceIsSet) { fml::AutoResetWaitableEvent latch; thread_host.raster_thread->GetTaskRunner()->PostTask([&] { - auto pipeline = std::make_shared(/*depth=*/10); + auto pipeline = std::make_shared(/*depth=*/10); auto layer_tree = std::make_unique( /*config=*/LayerTree::Config(), /*frame_size=*/SkISize()); auto layer_tree_item = std::make_unique( @@ -552,7 +552,7 @@ TEST(RasterizerTest, externalViewEmbedderDoesntEndFrameWhenNotUsedThisFrame) { fml::AutoResetWaitableEvent latch; thread_host.raster_thread->GetTaskRunner()->PostTask([&] { - auto pipeline = std::make_shared(/*depth=*/10); + auto pipeline = std::make_shared(/*depth=*/10); auto layer_tree = std::make_unique( /*config=*/LayerTree::Config(), /*frame_size=*/SkISize()); auto layer_tree_item = std::make_unique( @@ -608,7 +608,7 @@ TEST(RasterizerTest, externalViewEmbedderDoesntEndFrameWhenPipelineIsEmpty) { fml::AutoResetWaitableEvent latch; thread_host.raster_thread->GetTaskRunner()->PostTask([&] { - auto pipeline = std::make_shared(/*depth=*/10); + auto pipeline = std::make_shared(/*depth=*/10); ON_CALL(delegate, ShouldDiscardLayerTree).WillByDefault(Return(false)); DrawStatus status = rasterizer->Draw(pipeline); EXPECT_EQ(status, DrawStatus::kPipelineEmpty); @@ -658,7 +658,7 @@ TEST(RasterizerTest, rasterizer->Setup(std::move(surface)); fml::AutoResetWaitableEvent latch; thread_host.raster_thread->GetTaskRunner()->PostTask([&] { - auto pipeline = std::make_shared(/*depth=*/10); + auto pipeline = std::make_shared(/*depth=*/10); auto layer_tree = std::make_unique( /*config=*/LayerTree::Config(), /*frame_size=*/SkISize()); auto layer_tree_item = std::make_unique( @@ -717,7 +717,7 @@ TEST( rasterizer->Setup(std::move(surface)); fml::AutoResetWaitableEvent latch; thread_host.raster_thread->GetTaskRunner()->PostTask([&] { - auto pipeline = std::make_shared(/*depth=*/10); + auto pipeline = std::make_shared(/*depth=*/10); auto layer_tree = std::make_unique( /*config=*/LayerTree::Config(), /*frame_size=*/SkISize()); auto layer_tree_item = std::make_unique( @@ -776,7 +776,7 @@ TEST( rasterizer->Setup(std::move(surface)); fml::AutoResetWaitableEvent latch; thread_host.raster_thread->GetTaskRunner()->PostTask([&] { - auto pipeline = std::make_shared(/*depth=*/10); + auto pipeline = std::make_shared(/*depth=*/10); auto layer_tree = std::make_unique( /*config=*/LayerTree::Config(), /*frame_size=*/SkISize()); auto layer_tree_item = std::make_unique( @@ -834,7 +834,7 @@ TEST( rasterizer->Setup(std::move(surface)); fml::AutoResetWaitableEvent latch; thread_host.raster_thread->GetTaskRunner()->PostTask([&] { - auto pipeline = std::make_shared(/*depth=*/10); + auto pipeline = std::make_shared(/*depth=*/10); auto layer_tree = std::make_unique( /*config=*/LayerTree::Config(), /*frame_size=*/SkISize()); auto layer_tree_item = std::make_unique( @@ -891,7 +891,7 @@ TEST( rasterizer->Setup(std::move(surface)); fml::AutoResetWaitableEvent latch; thread_host.raster_thread->GetTaskRunner()->PostTask([&] { - auto pipeline = std::make_shared(/*depth=*/10); + auto pipeline = std::make_shared(/*depth=*/10); auto layer_tree = std::make_unique( /*config=*/LayerTree::Config(), /*frame_size=*/SkISize()); auto layer_tree_item = std::make_unique( @@ -972,7 +972,7 @@ TEST(RasterizerTest, thread_host.raster_thread->GetTaskRunner()->PostTask([&] { rasterizer->Setup(std::move(surface)); - auto pipeline = std::make_shared(/*depth=*/10); + auto pipeline = std::make_shared(/*depth=*/10); for (int i = 0; i < 2; i++) { auto layer_tree = std::make_unique( /*config=*/LayerTree::Config(), /*frame_size=*/SkISize()); @@ -1144,7 +1144,7 @@ TEST(RasterizerTest, presentationTimeSetWhenVsyncTargetInFuture) { thread_host.raster_thread->GetTaskRunner()->PostTask([&] { rasterizer->Setup(std::move(surface)); - auto pipeline = std::make_shared(/*depth=*/10); + auto pipeline = std::make_shared(/*depth=*/10); for (int i = 0; i < 2; i++) { auto layer_tree = std::make_unique( /*config=*/LayerTree::Config(), /*frame_size=*/SkISize()); @@ -1228,7 +1228,7 @@ TEST(RasterizerTest, presentationTimeNotSetWhenVsyncTargetInPast) { thread_host.raster_thread->GetTaskRunner()->PostTask([&] { rasterizer->Setup(std::move(surface)); - auto pipeline = std::make_shared(/*depth=*/10); + auto pipeline = std::make_shared(/*depth=*/10); auto layer_tree = std::make_unique( /*config=*/LayerTree::Config(), /*frame_size=*/SkISize()); auto layer_tree_item = std::make_unique( diff --git a/shell/common/shell.cc b/shell/common/shell.cc index ca3d591c39d15..d2b690a700e72 100644 --- a/shell/common/shell.cc +++ b/shell/common/shell.cc @@ -1215,16 +1215,16 @@ void Shell::OnAnimatorUpdateLatestFrameTargetTime( } // |Animator::Delegate| -void Shell::OnAnimatorDraw(std::shared_ptr pipeline) { +void Shell::OnAnimatorDraw(std::shared_ptr pipeline) { FML_DCHECK(is_set_up_); task_runners_.GetRasterTaskRunner()->PostTask(fml::MakeCopyable( [&waiting_for_first_frame = waiting_for_first_frame_, &waiting_for_first_frame_condition = waiting_for_first_frame_condition_, rasterizer = rasterizer_->GetWeakPtr(), - weak_pipeline = std::weak_ptr(pipeline)]() mutable { + weak_pipeline = std::weak_ptr(pipeline)]() mutable { if (rasterizer) { - std::shared_ptr pipeline = weak_pipeline.lock(); + std::shared_ptr pipeline = weak_pipeline.lock(); if (pipeline) { rasterizer->Draw(pipeline); } diff --git a/shell/common/shell.h b/shell/common/shell.h index b8c9c31052df6..f148593bd1ecf 100644 --- a/shell/common/shell.h +++ b/shell/common/shell.h @@ -640,7 +640,7 @@ class Shell final : public PlatformView::Delegate, fml::TimePoint frame_target_time) override; // |Animator::Delegate| - void OnAnimatorDraw(std::shared_ptr pipeline) override; + void OnAnimatorDraw(std::shared_ptr pipeline) override; // |Animator::Delegate| void OnAnimatorDrawLastLayerTree( From 8cc0657b2735429d26e4044e9383181c24aaef89 Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Wed, 20 Sep 2023 14:11:17 -0700 Subject: [PATCH 40/48] Format --- shell/common/animator.h | 3 +-- shell/common/rasterizer.cc | 13 ++++++------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/shell/common/animator.h b/shell/common/animator.h index 5e78c9fbd9c23..3ace82dbfd61a 100644 --- a/shell/common/animator.h +++ b/shell/common/animator.h @@ -39,8 +39,7 @@ class Animator final { virtual void OnAnimatorUpdateLatestFrameTargetTime( fml::TimePoint frame_target_time) = 0; - virtual void OnAnimatorDraw( - std::shared_ptr pipeline) = 0; + virtual void OnAnimatorDraw(std::shared_ptr pipeline) = 0; virtual void OnAnimatorDrawLastLayerTree( std::unique_ptr frame_timings_recorder) = 0; diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index 41d79c89cd037..bb440c605a9dd 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -218,8 +218,7 @@ void Rasterizer::DrawLastLayerTree( } } -DrawStatus Rasterizer::Draw( - const std::shared_ptr& pipeline) { +DrawStatus Rasterizer::Draw(const std::shared_ptr& pipeline) { TRACE_EVENT0("flutter", "GPURasterizer::Draw"); if (raster_thread_merger_ && !raster_thread_merger_->IsOnRasterizingThread()) { @@ -231,11 +230,11 @@ DrawStatus Rasterizer::Draw( ->RunsTasksOnCurrentThread()); DoDrawResult draw_result; - FramePipeline::Consumer consumer = - [&draw_result, this](std::unique_ptr item) { - draw_result = DoDraw(std::move(item->frame_timings_recorder), - std::move(item->layer_tree_tasks)); - }; + FramePipeline::Consumer consumer = [&draw_result, + this](std::unique_ptr item) { + draw_result = DoDraw(std::move(item->frame_timings_recorder), + std::move(item->layer_tree_tasks)); + }; PipelineConsumeResult consume_result = pipeline->Consume(consumer); if (consume_result == PipelineConsumeResult::NoneAvailable) { From 526f23358e7dc041d531bc6ec9ba53e4233c8f57 Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Wed, 20 Sep 2023 16:35:56 -0700 Subject: [PATCH 41/48] Fix doc --- shell/common/rasterizer.h | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/shell/common/rasterizer.h b/shell/common/rasterizer.h index e98e70b88568a..f50095dc36d16 100644 --- a/shell/common/rasterizer.h +++ b/shell/common/rasterizer.h @@ -608,11 +608,10 @@ class Rasterizer final : public SnapshotDelegate, // The result of `DoDraw`. // - // Normally `DoDraw` returns simply a raster status. However, sometimes we - // need to attempt to rasterize the layer tree again. This happens when - // layer_tree has not successfully rasterized due to changes in the thread - // configuration, in which case the resubmitted task will be inserted to the - // front of the pipeline. + // Normally `DoDraw` simply returns a status. However, sometimes we need to + // attempt to rasterize the layer tree again. See RasterStatus::kResubmit and + // kSkipAndRetry for when it happens. In such cases, `resubmitted_item` will + // not be null and its `tasks` will not be empty. struct DoDrawResult { DoDrawStatus status = DoDrawStatus::kDone; From 15c1af07b02e066e2964b39ac20c05c210d96f13 Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Wed, 20 Sep 2023 16:42:00 -0700 Subject: [PATCH 42/48] Move LayerTreeTask back --- flow/layers/layer_tree.h | 16 ++++++++++++++++ shell/common/rasterizer.h | 16 ---------------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/flow/layers/layer_tree.h b/flow/layers/layer_tree.h index 5f573da2099a0..013cfe9f422ff 100644 --- a/flow/layers/layer_tree.h +++ b/flow/layers/layer_tree.h @@ -94,6 +94,22 @@ class LayerTree { FML_DISALLOW_COPY_AND_ASSIGN(LayerTree); }; +// The information to draw a layer tree to a specified view. +struct LayerTreeTask { + LayerTreeTask(int64_t view_id, + std::unique_ptr layer_tree, + float device_pixel_ratio) + : view_id(view_id), + layer_tree(std::move(layer_tree)), + device_pixel_ratio(device_pixel_ratio) {} + /// The target view to drawn to. + int64_t view_id; + /// The target layer tree to be drawn. + std::unique_ptr layer_tree; + /// The pixel ratio of the target view. + float device_pixel_ratio; +}; + } // namespace flutter #endif // FLUTTER_FLOW_LAYERS_LAYER_TREE_H_ diff --git a/shell/common/rasterizer.h b/shell/common/rasterizer.h index f50095dc36d16..01d4bcec79c65 100644 --- a/shell/common/rasterizer.h +++ b/shell/common/rasterizer.h @@ -85,22 +85,6 @@ enum class DrawSurfaceStatus { kDiscarded, }; -// The information to draw a layer tree to a specified view. -struct LayerTreeTask { - LayerTreeTask(int64_t view_id, - std::unique_ptr layer_tree, - float device_pixel_ratio) - : view_id(view_id), - layer_tree(std::move(layer_tree)), - device_pixel_ratio(device_pixel_ratio) {} - /// The target view to drawn to. - int64_t view_id; - /// The target layer tree to be drawn. - std::unique_ptr layer_tree; - /// The pixel ratio of the target view. - float device_pixel_ratio; -}; - // The information to draw to all views of a frame. struct FrameItem { FrameItem(std::list tasks, From 797a88c978e1bc6754b4fc71fa973acfc72d8656 Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Tue, 26 Sep 2023 12:51:32 -0700 Subject: [PATCH 43/48] Change to vector unique_ptr --- flow/layers/layer_tree.h | 5 ++++ shell/common/animator.cc | 6 ++--- shell/common/rasterizer.cc | 40 ++++++++++++++-------------- shell/common/rasterizer.h | 26 +++++++++--------- shell/common/rasterizer_unittests.cc | 7 ++--- 5 files changed, 46 insertions(+), 38 deletions(-) diff --git a/flow/layers/layer_tree.h b/flow/layers/layer_tree.h index 013cfe9f422ff..6119ea524c707 100644 --- a/flow/layers/layer_tree.h +++ b/flow/layers/layer_tree.h @@ -96,18 +96,23 @@ class LayerTree { // The information to draw a layer tree to a specified view. struct LayerTreeTask { + public: LayerTreeTask(int64_t view_id, std::unique_ptr layer_tree, float device_pixel_ratio) : view_id(view_id), layer_tree(std::move(layer_tree)), device_pixel_ratio(device_pixel_ratio) {} + /// The target view to drawn to. int64_t view_id; /// The target layer tree to be drawn. std::unique_ptr layer_tree; /// The pixel ratio of the target view. float device_pixel_ratio; + + private: + FML_DISALLOW_COPY(LayerTreeTask); }; } // namespace flutter diff --git a/shell/common/animator.cc b/shell/common/animator.cc index 8588bc7947bbc..732b7338fa1fe 100644 --- a/shell/common/animator.cc +++ b/shell/common/animator.cc @@ -163,9 +163,9 @@ void Animator::Render(std::unique_ptr layer_tree, // TODO(dkwingsmt): Currently only supports a single window. int64_t view_id = kFlutterImplicitViewId; - std::list layer_trees_tasks; - layer_trees_tasks.emplace_back(view_id, std::move(layer_tree), - device_pixel_ratio); + std::vector> layer_trees_tasks; + layer_trees_tasks.push_back(std::make_unique( + view_id, std::move(layer_tree), device_pixel_ratio)); // Commit the pending continuation. PipelineProduceResult result = producer_continuation_.Complete(std::make_unique( diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index fefc6faaf51ba..128d0b4c0851a 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -194,7 +194,7 @@ flutter::LayerTree* Rasterizer::GetLastLayerTree(int64_t view_id) { if (found == last_successful_tasks_.end()) { return nullptr; } - return found->second.layer_tree.get(); + return found->second->layer_tree.get(); } void Rasterizer::DrawLastLayerTree( @@ -202,7 +202,7 @@ void Rasterizer::DrawLastLayerTree( if (last_successful_tasks_.empty() || !surface_) { return; } - std::list tasks; + std::vector> tasks; for (auto& [view_id, task] : last_successful_tasks_) { tasks.push_back(std::move(task)); } @@ -421,7 +421,7 @@ fml::Milliseconds Rasterizer::GetFrameBudget() const { Rasterizer::DoDrawResult Rasterizer::DoDraw( std::unique_ptr frame_timings_recorder, - std::list tasks) { + std::vector> tasks) { TRACE_EVENT_WITH_FRAME_NUMBER(frame_timings_recorder, "flutter", "Rasterizer::DoDraw", /*flow_id_count=*/0, /*flow_ids=*/nullptr); @@ -525,7 +525,7 @@ Rasterizer::DoDrawResult Rasterizer::DoDraw( Rasterizer::DoDrawResult Rasterizer::DrawToSurfaces( FrameTimingsRecorder& frame_timings_recorder, - std::list tasks) { + std::vector> tasks) { TRACE_EVENT0("flutter", "Rasterizer::DrawToSurfaces"); FML_DCHECK(surface_); frame_timings_recorder.AssertInState(FrameTimingsRecorder::State::kBuildEnd); @@ -556,12 +556,12 @@ Rasterizer::DoDrawResult Rasterizer::DrawToSurfaces( std::unique_ptr Rasterizer::DrawToSurfacesUnsafe( FrameTimingsRecorder& frame_timings_recorder, - std::list tasks) { + std::vector> tasks) { // TODO(dkwingsmt): The rasterizer only supports rendering a single view // and that view must be the implicit view. Properly support multi-view // in the future. FML_CHECK(tasks.size() == 1u); - FML_DCHECK(tasks.front().view_id == kFlutterImplicitViewId); + FML_DCHECK(tasks.front()->view_id == kFlutterImplicitViewId); compositor_context_->ui_time().SetLapTime( frame_timings_recorder.GetBuildDuration()); @@ -569,9 +569,9 @@ std::unique_ptr Rasterizer::DrawToSurfacesUnsafe( // First traverse: Filter out discarded trees auto task_iter = tasks.begin(); while (task_iter != tasks.end()) { - if (delegate_.ShouldDiscardLayerTree(task_iter->view_id, - *task_iter->layer_tree)) { - last_draw_statuses_[task_iter->view_id] = DrawSurfaceStatus::kDiscarded; + LayerTreeTask& task = **task_iter; + if (delegate_.ShouldDiscardLayerTree(task.view_id, *task.layer_tree)) { + last_draw_statuses_[task.view_id] = DrawSurfaceStatus::kDiscarded; task_iter = tasks.erase(task_iter); } else { ++task_iter; @@ -588,8 +588,8 @@ std::unique_ptr Rasterizer::DrawToSurfacesUnsafe( external_view_embedder_->SetUsedThisFrame(true); external_view_embedder_->BeginFrame( // TODO(dkwingsmt): Add all views here. - tasks.front().layer_tree->frame_size(), surface_->GetContext(), - tasks.front().device_pixel_ratio, raster_thread_merger_); + tasks.front()->layer_tree->frame_size(), surface_->GetContext(), + tasks.front()->device_pixel_ratio, raster_thread_merger_); } std::optional presentation_time = std::nullopt; @@ -607,11 +607,11 @@ std::unique_ptr Rasterizer::DrawToSurfacesUnsafe( frame_timings_recorder.RecordRasterStart(fml::TimePoint::Now()); // Second traverse: draw all layer trees. - std::list resubmitted_tasks; - for (LayerTreeTask& task : tasks) { - int64_t view_id = task.view_id; - std::unique_ptr layer_tree = std::move(task.layer_tree); - float device_pixel_ratio = task.device_pixel_ratio; + std::vector> resubmitted_tasks; + for (std::unique_ptr& task : tasks) { + int64_t view_id = task->view_id; + std::unique_ptr layer_tree = std::move(task->layer_tree); + float device_pixel_ratio = task->device_pixel_ratio; DrawSurfaceStatus status = DrawToSurfaceUnsafe( view_id, *layer_tree, device_pixel_ratio, presentation_time); @@ -619,11 +619,11 @@ std::unique_ptr Rasterizer::DrawToSurfacesUnsafe( last_draw_statuses_[view_id] = status; if (status == DrawSurfaceStatus::kSuccess) { last_successful_tasks_.insert_or_assign( - view_id, - LayerTreeTask(view_id, std::move(layer_tree), device_pixel_ratio)); + view_id, std::make_unique( + view_id, std::move(layer_tree), device_pixel_ratio)); } else if (status == DrawSurfaceStatus::kRetry) { - resubmitted_tasks.emplace_back(view_id, std::move(layer_tree), - device_pixel_ratio); + resubmitted_tasks.push_back(std::make_unique( + view_id, std::move(layer_tree), device_pixel_ratio)); } } // TODO(dkwingsmt): Pass in all raster caches diff --git a/shell/common/rasterizer.h b/shell/common/rasterizer.h index 01d4bcec79c65..bd9ea6805a5f9 100644 --- a/shell/common/rasterizer.h +++ b/shell/common/rasterizer.h @@ -58,9 +58,9 @@ enum class DrawStatus { // Nothing was done, because the call was not on the raster thread. Yielded to // let this frame be serviced on the right thread. kYielded, - // Nothing was done, because pipeline was empty. + // Nothing was done, because the pipeline was empty. kPipelineEmpty, - // Nothing was done, because GPU was unavailable. + // Nothing was done, because the GPU was unavailable. kGpuUnavailable, }; @@ -87,11 +87,11 @@ enum class DrawSurfaceStatus { // The information to draw to all views of a frame. struct FrameItem { - FrameItem(std::list tasks, + FrameItem(std::vector> tasks, std::unique_ptr frame_timings_recorder) : layer_tree_tasks(std::move(tasks)), frame_timings_recorder(std::move(frame_timings_recorder)) {} - std::list layer_tree_tasks; + std::vector> layer_tree_tasks; std::unique_ptr frame_timings_recorder; }; @@ -229,7 +229,7 @@ class Rasterizer final : public SnapshotDelegate, /// collects associated resources. No more rendering may occur /// till the next call to `Rasterizer::Setup` with a new render /// surface. Calling a teardown without a setup is user error. - /// Calling this method for multiple times is safe. + /// Calling this method multiple times is safe. /// void Teardown(); @@ -564,14 +564,14 @@ class Rasterizer final : public SnapshotDelegate, //---------------------------------------------------------------------------- /// @brief Returns whether TearDown has been called. /// - /// This method is only used only in unit tests. + /// This method is used only in unit tests. /// bool IsTornDown(); //---------------------------------------------------------------------------- /// @brief Returns the last status of drawing the specific view. /// - /// This method is only used only in unit tests. + /// This method is used only in unit tests. /// std::optional GetLastDrawStatus(int64_t view_id); @@ -662,11 +662,12 @@ class Rasterizer final : public SnapshotDelegate, // the middle and not get the recorded time. DoDrawResult DoDraw( std::unique_ptr frame_timings_recorder, - std::list tasks); + std::vector> tasks); // This method pushes the frame timing recorder from build end to raster end. - DoDrawResult DrawToSurfaces(FrameTimingsRecorder& frame_timings_recorder, - std::list tasks); + DoDrawResult DrawToSurfaces( + FrameTimingsRecorder& frame_timings_recorder, + std::vector> tasks); // Draws the specified layer trees to views, assuming we have access to the // GPU. @@ -680,7 +681,7 @@ class Rasterizer final : public SnapshotDelegate, // This method pushes the frame timing recorder from build end to raster end. std::unique_ptr DrawToSurfacesUnsafe( FrameTimingsRecorder& frame_timings_recorder, - std::list tasks); + std::vector> tasks); // Draws the layer tree to the specified view, assuming we have access to the // GPU. @@ -706,7 +707,8 @@ class Rasterizer final : public SnapshotDelegate, std::unique_ptr snapshot_surface_producer_; std::unique_ptr compositor_context_; // TODO(dkwingsmt): Probably merge them. - std::unordered_map last_successful_tasks_; + std::unordered_map> + last_successful_tasks_; std::unordered_map last_draw_statuses_; fml::closure next_frame_callback_; bool user_override_resource_cache_bytes_; diff --git a/shell/common/rasterizer_unittests.cc b/shell/common/rasterizer_unittests.cc index 15a7305450e20..010148ad1e924 100644 --- a/shell/common/rasterizer_unittests.cc +++ b/shell/common/rasterizer_unittests.cc @@ -34,12 +34,13 @@ namespace { constexpr float kDevicePixelRatio = 2.0f; constexpr int64_t kImplicitViewId = 0; -std::list SingleLayerTreeList( +std::vector> SingleLayerTreeList( int64_t view_id, std::unique_ptr layer_tree, float pixel_ratio) { - std::list tasks; - tasks.emplace_back(view_id, std::move(layer_tree), pixel_ratio); + std::vector> tasks; + tasks.push_back(std::make_unique( + view_id, std::move(layer_tree), pixel_ratio)); return tasks; } From f752d0a64c20a0ee18711cf13a76ec7eb136f95a Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Tue, 26 Sep 2023 13:25:32 -0700 Subject: [PATCH 44/48] Doc fix --- flow/compositor_context.h | 4 ++-- flow/frame_timings.h | 7 ++++--- shell/common/rasterizer.cc | 5 ++--- shell/common/rasterizer.h | 6 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/flow/compositor_context.h b/flow/compositor_context.h index 3ef31417d7509..453259cd67279 100644 --- a/flow/compositor_context.h +++ b/flow/compositor_context.h @@ -27,7 +27,7 @@ class LayerTree; enum class RasterStatus { // Frame has been successfully rasterized. kSuccess, - // Frame has been submited, but should be submitted again. This is only used + // Frame has been submited, but must be submitted again. This is only used // on Android when switching the background surface to FlutterImageView. // // On Android, the first frame doesn't make the image available @@ -35,7 +35,7 @@ enum class RasterStatus { // // TODO(egarciad): https://github.com/flutter/flutter/issues/65652 kResubmit, - // Frame should be dropped and a new frame with the same layer tree should be + // Frame has be dropped and a new frame with the same layer tree must be // attempted. // // This is currently used to wait for the thread merger to merge diff --git a/flow/frame_timings.h b/flow/frame_timings.h index 06f6f0b53f606..c81bcc3362298 100644 --- a/flow/frame_timings.h +++ b/flow/frame_timings.h @@ -116,10 +116,11 @@ class FrameTimingsRecorder { /// Returns the recorded time from when `RecordRasterEnd` is called. FrameTiming GetRecordedTime() const; - /// Asserts in debug mode that the recorder is current at the specified state. - /// - /// A `GetState` method is not preferred to avoid other logic relying on this + /// Asserts in unopt builds that the recorder is current at the specified /// state. + /// + /// Instead of adding a `GetState` method and asserting on the result, this + /// method prevents other logic from relying on the state. void AssertInState(State state) const; private: diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index 128d0b4c0851a..b7ef1f4ded421 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -299,11 +299,10 @@ DrawStatus Rasterizer::ToDrawStatus(DoDrawStatus status) { return DrawStatus::kNotSetUp; case DoDrawStatus::kGpuUnavailable: return DrawStatus::kGpuUnavailable; - default: - FML_CHECK(status == DoDrawStatus::kDone) - << "Unrecognized status " << (int)status; + case DoDrawStatus::kDone: return DrawStatus::kDone; } + FML_UNREACHABLE(); } namespace { diff --git a/shell/common/rasterizer.h b/shell/common/rasterizer.h index bd9ea6805a5f9..52c0954f5e6f6 100644 --- a/shell/common/rasterizer.h +++ b/shell/common/rasterizer.h @@ -68,7 +68,7 @@ enum class DrawStatus { enum class DrawSurfaceStatus { // The layer tree was successfully rasterized. kSuccess, - // The layer tree should be submitted again. + // The layer tree must be submitted again. // // This can occur on Android when switching the background surface to // FlutterImageView. On Android, the first frame doesn't make the image @@ -261,7 +261,7 @@ class Rasterizer final : public SnapshotDelegate, //---------------------------------------------------------------------------- /// @brief Deallocate the resources for displaying a view. /// - /// This method should be called when a view is removed. + /// This method must be called when a view is removed. /// /// The rasterizer don't need views to be registered. Last-frame /// states for views are recorded when layer trees are rasterized @@ -686,7 +686,7 @@ class Rasterizer final : public SnapshotDelegate, // Draws the layer tree to the specified view, assuming we have access to the // GPU. // - // This method is not affiliated with the frame timing recorder, but should be + // This method is not affiliated with the frame timing recorder, but must be // included between the RasterStart and RasterEnd. DrawSurfaceStatus DrawToSurfaceUnsafe( int64_t view_id, From 69550b3e87565a0437cddb4477d2c9614f4dbf12 Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Tue, 26 Sep 2023 15:10:20 -0700 Subject: [PATCH 45/48] Merge to ViewRecord --- runtime/runtime_delegate.h | 2 +- shell/common/animator.cc | 24 +++++----- shell/common/animator.h | 10 ++-- shell/common/animator_unittests.cc | 2 +- shell/common/engine.cc | 4 +- shell/common/engine.h | 2 +- shell/common/rasterizer.cc | 53 +++++++++++++-------- shell/common/rasterizer.h | 71 ++++++++++++++++------------ shell/common/rasterizer_unittests.cc | 6 +-- shell/common/shell.cc | 6 +-- shell/common/shell.h | 2 +- 11 files changed, 102 insertions(+), 80 deletions(-) diff --git a/runtime/runtime_delegate.h b/runtime/runtime_delegate.h index a036d4723cb34..bc3de031f4411 100644 --- a/runtime/runtime_delegate.h +++ b/runtime/runtime_delegate.h @@ -23,7 +23,7 @@ class RuntimeDelegate { public: virtual std::string DefaultRouteName() = 0; - virtual void ScheduleFrame(bool regenerate_layer_tree = true) = 0; + virtual void ScheduleFrame(bool regenerate_layer_trees = true) = 0; virtual void Render(std::unique_ptr layer_tree, float device_pixel_ratio) = 0; diff --git a/shell/common/animator.cc b/shell/common/animator.cc index 732b7338fa1fe..1971ce8c58f30 100644 --- a/shell/common/animator.cc +++ b/shell/common/animator.cc @@ -85,7 +85,7 @@ void Animator::BeginFrame( } frame_scheduled_ = false; - regenerate_layer_tree_ = false; + regenerate_layer_trees_ = false; pending_frame_semaphore_.Signal(); if (!producer_continuation_) { @@ -191,15 +191,15 @@ const std::weak_ptr Animator::GetVsyncWaiter() const { return weak; } -bool Animator::CanReuseLastLayerTree() { - return !regenerate_layer_tree_; +bool Animator::CanReuseLastLayerTrees() { + return !regenerate_layer_trees_; } -void Animator::DrawLastLayerTree( +void Animator::DrawLastLayerTrees( std::unique_ptr frame_timings_recorder) { // This method is very cheap, but this makes it explicitly clear in trace // files. - TRACE_EVENT0("flutter", "Animator::DrawLastLayerTree"); + TRACE_EVENT0("flutter", "Animator::DrawLastLayerTrees"); pending_frame_semaphore_.Signal(); // In this case BeginFrame doesn't get called, we need to @@ -209,18 +209,18 @@ void Animator::DrawLastLayerTree( const auto now = fml::TimePoint::Now(); frame_timings_recorder->RecordBuildStart(now); frame_timings_recorder->RecordBuildEnd(now); - delegate_.OnAnimatorDrawLastLayerTree(std::move(frame_timings_recorder)); + delegate_.OnAnimatorDrawLastLayerTrees(std::move(frame_timings_recorder)); } -void Animator::RequestFrame(bool regenerate_layer_tree) { - if (regenerate_layer_tree) { +void Animator::RequestFrame(bool regenerate_layer_trees) { + if (regenerate_layer_trees) { // This event will be closed by BeginFrame. BeginFrame will only be called - // if regenerating the layer tree. If a frame has been requested to update + // if regenerating the layer trees. If a frame has been requested to update // an external texture, this will be false and no BeginFrame call will // happen. TRACE_EVENT_ASYNC_BEGIN0("flutter", "Frame Request Pending", frame_request_number_); - regenerate_layer_tree_ = true; + regenerate_layer_trees_ = true; } if (!pending_frame_semaphore_.TryWait()) { @@ -251,8 +251,8 @@ void Animator::AwaitVSync() { [self = weak_factory_.GetWeakPtr()]( std::unique_ptr frame_timings_recorder) { if (self) { - if (self->CanReuseLastLayerTree()) { - self->DrawLastLayerTree(std::move(frame_timings_recorder)); + if (self->CanReuseLastLayerTrees()) { + self->DrawLastLayerTrees(std::move(frame_timings_recorder)); } else { self->BeginFrame(std::move(frame_timings_recorder)); } diff --git a/shell/common/animator.h b/shell/common/animator.h index 3ace82dbfd61a..8a92705ede9e6 100644 --- a/shell/common/animator.h +++ b/shell/common/animator.h @@ -41,7 +41,7 @@ class Animator final { virtual void OnAnimatorDraw(std::shared_ptr pipeline) = 0; - virtual void OnAnimatorDrawLastLayerTree( + virtual void OnAnimatorDrawLastLayerTrees( std::unique_ptr frame_timings_recorder) = 0; }; @@ -51,7 +51,7 @@ class Animator final { ~Animator(); - void RequestFrame(bool regenerate_layer_tree = true); + void RequestFrame(bool regenerate_layer_trees = true); void Render(std::unique_ptr layer_tree, float device_pixel_ratio); @@ -84,9 +84,9 @@ class Animator final { private: void BeginFrame(std::unique_ptr frame_timings_recorder); - bool CanReuseLastLayerTree(); + bool CanReuseLastLayerTrees(); - void DrawLastLayerTree( + void DrawLastLayerTrees( std::unique_ptr frame_timings_recorder); void AwaitVSync(); @@ -104,7 +104,7 @@ class Animator final { std::shared_ptr layer_tree_pipeline_; fml::Semaphore pending_frame_semaphore_; FramePipeline::ProducerContinuation producer_continuation_; - bool regenerate_layer_tree_ = false; + bool regenerate_layer_trees_ = false; bool frame_scheduled_ = false; std::deque trace_flow_ids_; bool has_rendered_ = false; diff --git a/shell/common/animator_unittests.cc b/shell/common/animator_unittests.cc index 60088357f9de4..9190659fc6f55 100644 --- a/shell/common/animator_unittests.cc +++ b/shell/common/animator_unittests.cc @@ -44,7 +44,7 @@ class FakeAnimatorDelegate : public Animator::Delegate { (std::shared_ptr pipeline), (override)); - void OnAnimatorDrawLastLayerTree( + void OnAnimatorDrawLastLayerTrees( std::unique_ptr frame_timings_recorder) override {} bool notify_idle_called_ = false; diff --git a/shell/common/engine.cc b/shell/common/engine.cc index 920122c9a23dc..ea0cb43d9be18 100644 --- a/shell/common/engine.cc +++ b/shell/common/engine.cc @@ -455,8 +455,8 @@ std::string Engine::DefaultRouteName() { return "/"; } -void Engine::ScheduleFrame(bool regenerate_layer_tree) { - animator_->RequestFrame(regenerate_layer_tree); +void Engine::ScheduleFrame(bool regenerate_layer_trees) { + animator_->RequestFrame(regenerate_layer_trees); } void Engine::Render(std::unique_ptr layer_tree, diff --git a/shell/common/engine.h b/shell/common/engine.h index f7d888de425f2..ba584ec504cf2 100644 --- a/shell/common/engine.h +++ b/shell/common/engine.h @@ -828,7 +828,7 @@ class Engine final : public RuntimeDelegate, PointerDataDispatcher::Delegate { void SetAccessibilityFeatures(int32_t flags); // |RuntimeDelegate| - void ScheduleFrame(bool regenerate_layer_tree) override; + void ScheduleFrame(bool regenerate_layer_trees) override; /// Schedule a frame with the default parameter of regenerating the layer /// tree. diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index b7ef1f4ded421..71f49e7cb913f 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -121,7 +121,7 @@ void Rasterizer::Teardown() { surface_.reset(); } - last_successful_tasks_.clear(); + view_records_.clear(); if (raster_thread_merger_.get() != nullptr && raster_thread_merger_.get()->IsMerged()) { @@ -137,9 +137,9 @@ bool Rasterizer::IsTornDown() { std::optional Rasterizer::GetLastDrawStatus( int64_t view_id) { - auto found = last_draw_statuses_.find(view_id); - if (found != last_draw_statuses_.end()) { - return found->second; + auto found = view_records_.find(view_id); + if (found != view_records_.end()) { + return found->second.last_draw_status; } else { return std::optional(); } @@ -177,8 +177,7 @@ void Rasterizer::NotifyLowMemoryWarning() const { } void Rasterizer::CollectView(int64_t view_id) { - last_successful_tasks_.erase(view_id); - last_draw_statuses_.erase(view_id); + view_records_.erase(view_id); } std::shared_ptr Rasterizer::GetTextureRegistry() { @@ -190,23 +189,31 @@ GrDirectContext* Rasterizer::GetGrContext() { } flutter::LayerTree* Rasterizer::GetLastLayerTree(int64_t view_id) { - auto found = last_successful_tasks_.find(view_id); - if (found == last_successful_tasks_.end()) { + auto found = view_records_.find(view_id); + if (found == view_records_.end()) { return nullptr; } - return found->second->layer_tree.get(); + auto& last_task = found->second.last_successful_task; + if (last_task == nullptr) { + return nullptr; + } + return last_task->layer_tree.get(); } -void Rasterizer::DrawLastLayerTree( +void Rasterizer::DrawLastLayerTrees( std::unique_ptr frame_timings_recorder) { - if (last_successful_tasks_.empty() || !surface_) { + if (!surface_) { return; } std::vector> tasks; - for (auto& [view_id, task] : last_successful_tasks_) { - tasks.push_back(std::move(task)); + for (auto& [view_id, view_record] : view_records_) { + if (view_record.last_successful_task) { + tasks.push_back(std::move(view_record.last_successful_task)); + } + } + if (tasks.empty()) { + return; } - last_successful_tasks_.clear(); DoDrawResult result = DrawToSurfaces(*frame_timings_recorder, std::move(tasks)); @@ -559,7 +566,7 @@ std::unique_ptr Rasterizer::DrawToSurfacesUnsafe( // TODO(dkwingsmt): The rasterizer only supports rendering a single view // and that view must be the implicit view. Properly support multi-view // in the future. - FML_CHECK(tasks.size() == 1u); + FML_CHECK(tasks.size() == 1u) << "Unexpected size of " << tasks.size(); FML_DCHECK(tasks.front()->view_id == kFlutterImplicitViewId); compositor_context_->ui_time().SetLapTime( @@ -570,7 +577,8 @@ std::unique_ptr Rasterizer::DrawToSurfacesUnsafe( while (task_iter != tasks.end()) { LayerTreeTask& task = **task_iter; if (delegate_.ShouldDiscardLayerTree(task.view_id, *task.layer_tree)) { - last_draw_statuses_[task.view_id] = DrawSurfaceStatus::kDiscarded; + EnsureViewRecord(task.view_id).last_draw_status = + DrawSurfaceStatus::kDiscarded; task_iter = tasks.erase(task_iter); } else { ++task_iter; @@ -614,12 +622,13 @@ std::unique_ptr Rasterizer::DrawToSurfacesUnsafe( DrawSurfaceStatus status = DrawToSurfaceUnsafe( view_id, *layer_tree, device_pixel_ratio, presentation_time); + FML_DCHECK(status != DrawSurfaceStatus::kDiscarded); - last_draw_statuses_[view_id] = status; + auto& view_record = EnsureViewRecord(task->view_id); + view_record.last_draw_status = status; if (status == DrawSurfaceStatus::kSuccess) { - last_successful_tasks_.insert_or_assign( - view_id, std::make_unique( - view_id, std::move(layer_tree), device_pixel_ratio)); + view_record.last_successful_task = std::make_unique( + view_id, std::move(layer_tree), device_pixel_ratio); } else if (status == DrawSurfaceStatus::kRetry) { resubmitted_tasks.push_back(std::make_unique( view_id, std::move(layer_tree), device_pixel_ratio)); @@ -762,6 +771,10 @@ DrawSurfaceStatus Rasterizer::DrawToSurfaceUnsafe( return DrawSurfaceStatus::kFailed; } +Rasterizer::ViewRecord& Rasterizer::EnsureViewRecord(int64_t view_id) { + return view_records_[view_id]; +} + static sk_sp ScreenshotLayerTreeAsPicture( flutter::LayerTree* tree, flutter::CompositorContext& compositor_context) { diff --git a/shell/common/rasterizer.h b/shell/common/rasterizer.h index 52c0954f5e6f6..e5acbaf8357a9 100644 --- a/shell/common/rasterizer.h +++ b/shell/common/rasterizer.h @@ -265,41 +265,42 @@ class Rasterizer final : public SnapshotDelegate, /// /// The rasterizer don't need views to be registered. Last-frame /// states for views are recorded when layer trees are rasterized - /// to the view and used during `Rasterizer::DrawLastLayerTree`. + /// to the view and used during `Rasterizer::DrawLastLayerTrees`. /// /// @param[in] view_id The ID of the view. /// void CollectView(int64_t view_id); //---------------------------------------------------------------------------- - /// @brief Sometimes, it may be necessary to render the same frame again - /// without having to wait for the framework to build a whole new - /// layer tree describing the same contents. One such case is when - /// external textures (video or camera streams for example) are - /// updated in an otherwise static layer tree. To support this use - /// case, the rasterizer holds onto the last rendered layer tree. + /// @brief Returns the last successfully drawn layer tree for the given + /// view, or nullptr if there isn't any. This is useful during + /// `DrawLastLayerTrees` and computing frame damage. /// /// @bug https://github.com/flutter/flutter/issues/33939 /// /// @return A pointer to the last layer or `nullptr` if this rasterizer - /// has never rendered a frame. + /// has never rendered a frame to the given view. /// flutter::LayerTree* GetLastLayerTree(int64_t view_id); //---------------------------------------------------------------------------- - /// @brief Draws a last layer tree to the render surface. This may seem - /// entirely redundant at first glance. After all, on surface loss - /// and re-acquisition, the framework generates a new layer tree. - /// Otherwise, why render the same contents to the screen again? - /// This is used as an optimization in cases where there are - /// external textures (video or camera streams for example) in - /// referenced in the layer tree. These textures may be updated at - /// a cadence different from that of the Flutter application. - /// Flutter can re-render the layer tree with just the updated - /// textures instead of waiting for the framework to do the work - /// to generate the layer tree describing the same contents. - /// - void DrawLastLayerTree( + /// @brief Draws the last layer trees with their last configuration. This + /// may seem entirely redundant at first glance. After all, on + /// surface loss and re-acquisition, the framework generates a new + /// layer tree. Otherwise, why render the same contents to the + /// screen again? This is used as an optimization in cases where + /// there are external textures (video or camera streams for + /// example) in referenced in the layer tree. These textures may + /// be updated at a cadence different from that of the Flutter + /// application. Flutter can re-render the layer tree with just + /// the updated textures instead of waiting for the framework to + /// do the work to generate the layer tree describing the same + /// contents. + /// + /// Calling this method clears all last layer trees + /// (GetLastLayerTree). + /// + void DrawLastLayerTrees( std::unique_ptr frame_timings_recorder); // |SnapshotDelegate| @@ -590,18 +591,27 @@ class Rasterizer final : public SnapshotDelegate, kGpuUnavailable, }; - // The result of `DoDraw`. - // - // Normally `DoDraw` simply returns a status. However, sometimes we need to - // attempt to rasterize the layer tree again. See RasterStatus::kResubmit and - // kSkipAndRetry for when it happens. In such cases, `resubmitted_item` will - // not be null and its `tasks` will not be empty. + // The result of DoDraw. struct DoDrawResult { + // The overall status of the drawing process. + // + // The status of drawing a specific view is available at GetLastDrawStatus. DoDrawStatus status = DoDrawStatus::kDone; + // The frame item that needs to be submitted again. + // + // See RasterStatus::kResubmit and kSkipAndRetry for when it happens. + // + // If `resubmitted_item` is not null, its `tasks` is guaranteed to be + // non-empty. std::unique_ptr resubmitted_item; }; + struct ViewRecord { + std::unique_ptr last_successful_task; + std::optional last_draw_status; + }; + // |SnapshotDelegate| std::unique_ptr MakeSkiaGpuImage( sk_sp display_list, @@ -694,6 +704,8 @@ class Rasterizer final : public SnapshotDelegate, float device_pixel_ratio, std::optional presentation_time); + ViewRecord& EnsureViewRecord(int64_t view_id); + void FireNextFrameCallbackIfPresent(); static bool ShouldResubmitFrame(const DoDrawResult& result); @@ -706,10 +718,7 @@ class Rasterizer final : public SnapshotDelegate, std::unique_ptr surface_; std::unique_ptr snapshot_surface_producer_; std::unique_ptr compositor_context_; - // TODO(dkwingsmt): Probably merge them. - std::unordered_map> - last_successful_tasks_; - std::unordered_map last_draw_statuses_; + std::unordered_map view_records_; fml::closure next_frame_callback_; bool user_override_resource_cache_bytes_; std::optional max_cache_bytes_; diff --git a/shell/common/rasterizer_unittests.cc b/shell/common/rasterizer_unittests.cc index 010148ad1e924..1e21d0d8f1ecb 100644 --- a/shell/common/rasterizer_unittests.cc +++ b/shell/common/rasterizer_unittests.cc @@ -421,7 +421,7 @@ TEST(RasterizerTest, /*frame_size=*/SkISize::Make(800, 600)); EXPECT_CALL(*surface, AllowsDrawingWhenGpuDisabled()) .WillRepeatedly(Return(true)); - // Prepare two frames for Draw() and DrawLastLayerTree(). + // Prepare two frames for Draw() and DrawLastLayerTrees(). EXPECT_CALL(*surface, AcquireFrame(SkISize())) .WillOnce(Return(ByMove(std::move(surface_frame1)))) .WillOnce(Return(ByMove(std::move(surface_frame2)))); @@ -458,9 +458,9 @@ TEST(RasterizerTest, ON_CALL(delegate, ShouldDiscardLayerTree).WillByDefault(Return(false)); rasterizer->Draw(pipeline); - // The DrawLastLayerTree() will respectively call BeginFrame(), SubmitFrame() + // The DrawLastLayerTrees() will respectively call BeginFrame(), SubmitFrame() // and EndFrame() one more time, totally 2 times. - rasterizer->DrawLastLayerTree(CreateFinishedBuildRecorder()); + rasterizer->DrawLastLayerTrees(CreateFinishedBuildRecorder()); } TEST(RasterizerTest, externalViewEmbedderDoesntEndFrameWhenNoSurfaceIsSet) { diff --git a/shell/common/shell.cc b/shell/common/shell.cc index 02cab3fe119b9..44e5d2a65e110 100644 --- a/shell/common/shell.cc +++ b/shell/common/shell.cc @@ -1243,7 +1243,7 @@ void Shell::OnAnimatorDraw(std::shared_ptr pipeline) { } // |Animator::Delegate| -void Shell::OnAnimatorDrawLastLayerTree( +void Shell::OnAnimatorDrawLastLayerTrees( std::unique_ptr frame_timings_recorder) { FML_DCHECK(is_set_up_); @@ -1251,7 +1251,7 @@ void Shell::OnAnimatorDrawLastLayerTree( [rasterizer = rasterizer_->GetWeakPtr(), frame_timings_recorder = std::move(frame_timings_recorder)]() mutable { if (rasterizer) { - rasterizer->DrawLastLayerTree(std::move(frame_timings_recorder)); + rasterizer->DrawLastLayerTrees(std::move(frame_timings_recorder)); } }); @@ -1987,7 +1987,7 @@ bool Shell::OnServiceProtocolRenderFrameWithRasterStats( frame_timings_recorder->RecordBuildEnd(now); last_layer_tree->enable_leaf_layer_tracing(true); - rasterizer_->DrawLastLayerTree(std::move(frame_timings_recorder)); + rasterizer_->DrawLastLayerTrees(std::move(frame_timings_recorder)); last_layer_tree->enable_leaf_layer_tracing(false); rapidjson::Value snapshots; diff --git a/shell/common/shell.h b/shell/common/shell.h index 4a1b8c35077ce..133fecc4d0f43 100644 --- a/shell/common/shell.h +++ b/shell/common/shell.h @@ -653,7 +653,7 @@ class Shell final : public PlatformView::Delegate, void OnAnimatorDraw(std::shared_ptr pipeline) override; // |Animator::Delegate| - void OnAnimatorDrawLastLayerTree( + void OnAnimatorDrawLastLayerTrees( std::unique_ptr frame_timings_recorder) override; // |Engine::Delegate| From 0eb5694c77fb9cf89d3f135ed2c1e943f8363964 Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Tue, 26 Sep 2023 16:10:06 -0700 Subject: [PATCH 46/48] Add issue links --- shell/common/animator.cc | 1 + shell/common/rasterizer.cc | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/shell/common/animator.cc b/shell/common/animator.cc index 1971ce8c58f30..3dd925cee6213 100644 --- a/shell/common/animator.cc +++ b/shell/common/animator.cc @@ -162,6 +162,7 @@ void Animator::Render(std::unique_ptr layer_tree, frame_timings_recorder_->GetVsyncTargetTime()); // TODO(dkwingsmt): Currently only supports a single window. + // See https://github.com/flutter/flutter/issues/135530, item 2. int64_t view_id = kFlutterImplicitViewId; std::vector> layer_trees_tasks; layer_trees_tasks.push_back(std::make_unique( diff --git a/shell/common/rasterizer.cc b/shell/common/rasterizer.cc index 71f49e7cb913f..7ab349d353f37 100644 --- a/shell/common/rasterizer.cc +++ b/shell/common/rasterizer.cc @@ -566,6 +566,7 @@ std::unique_ptr Rasterizer::DrawToSurfacesUnsafe( // TODO(dkwingsmt): The rasterizer only supports rendering a single view // and that view must be the implicit view. Properly support multi-view // in the future. + // See https://github.com/flutter/flutter/issues/135530, item 2 & 4. FML_CHECK(tasks.size() == 1u) << "Unexpected size of " << tasks.size(); FML_DCHECK(tasks.front()->view_id == kFlutterImplicitViewId); @@ -595,6 +596,7 @@ std::unique_ptr Rasterizer::DrawToSurfacesUnsafe( external_view_embedder_->SetUsedThisFrame(true); external_view_embedder_->BeginFrame( // TODO(dkwingsmt): Add all views here. + // See https://github.com/flutter/flutter/issues/135530, item 4. tasks.front()->layer_tree->frame_size(), surface_->GetContext(), tasks.front()->device_pixel_ratio, raster_thread_merger_); } @@ -634,7 +636,8 @@ std::unique_ptr Rasterizer::DrawToSurfacesUnsafe( view_id, std::move(layer_tree), device_pixel_ratio)); } } - // TODO(dkwingsmt): Pass in all raster caches + // TODO(dkwingsmt): Pass in raster cache(s) for all views. + // See https://github.com/flutter/flutter/issues/135530, item 4. frame_timings_recorder.RecordRasterEnd(&compositor_context_->raster_cache()); FireNextFrameCallbackIfPresent(); @@ -864,6 +867,8 @@ Rasterizer::Screenshot Rasterizer::ScreenshotLastLayerTree( bool base64_encode) { // TODO(dkwingsmt): Support screenshotting all last layer trees // when the shell protocol supports multi-views. + // https://github.com/flutter/flutter/issues/135534 + // https://github.com/flutter/flutter/issues/135535 auto* layer_tree = GetLastLayerTree(kFlutterImplicitViewId); if (layer_tree == nullptr) { FML_LOG(ERROR) << "Last layer tree was null when screenshotting."; From 0540cadda61388dde49f91540a6a215f200d9ea1 Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Fri, 29 Sep 2023 12:57:23 -0700 Subject: [PATCH 47/48] Fix comment --- flow/layers/layer_tree.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/flow/layers/layer_tree.h b/flow/layers/layer_tree.h index 6119ea524c707..af162d58e0c4f 100644 --- a/flow/layers/layer_tree.h +++ b/flow/layers/layer_tree.h @@ -104,7 +104,7 @@ struct LayerTreeTask { layer_tree(std::move(layer_tree)), device_pixel_ratio(device_pixel_ratio) {} - /// The target view to drawn to. + /// The target view to draw to. int64_t view_id; /// The target layer tree to be drawn. std::unique_ptr layer_tree; @@ -112,7 +112,7 @@ struct LayerTreeTask { float device_pixel_ratio; private: - FML_DISALLOW_COPY(LayerTreeTask); + FML_DISALLOW_COPY_AND_ASSIGN(LayerTreeTask); }; } // namespace flutter From 6b9c423d29c84d7fb65c40febe653834868f4537 Mon Sep 17 00:00:00 2001 From: Tong Mu Date: Fri, 29 Sep 2023 13:26:29 -0700 Subject: [PATCH 48/48] Remove unnecessary include --- shell/common/engine.h | 1 - 1 file changed, 1 deletion(-) diff --git a/shell/common/engine.h b/shell/common/engine.h index ba584ec504cf2..a60d8b81f8ed4 100644 --- a/shell/common/engine.h +++ b/shell/common/engine.h @@ -29,7 +29,6 @@ #include "flutter/shell/common/display_manager.h" #include "flutter/shell/common/platform_view.h" #include "flutter/shell/common/pointer_data_dispatcher.h" -#include "flutter/shell/common/rasterizer.h" #include "flutter/shell/common/run_configuration.h" #include "flutter/shell/common/shell_io_manager.h"