@@ -250,19 +250,38 @@ Engine::Engine(Delegate& delegate,
250250 // Setup the callback that will instantiate the rasterizer.
251251 flutter::Shell::CreateCallback<flutter::Rasterizer> on_create_rasterizer;
252252#if defined(LEGACY_FUCHSIA_EMBEDDER)
253- on_create_rasterizer = [this ](flutter::Shell& shell) {
253+ on_create_rasterizer = [this , &product_config ](flutter::Shell& shell) {
254254 if (use_legacy_renderer_) {
255255 FML_DCHECK (session_connection_);
256256 FML_DCHECK (surface_producer_);
257257 FML_DCHECK (legacy_external_view_embedder_);
258258
259+ if (product_config.enable_shader_warmup ()) {
260+ FML_DCHECK (surface_producer_);
261+ WarmupSkps (shell.GetDartVM ()
262+ ->GetConcurrentMessageLoop ()
263+ ->GetTaskRunner ()
264+ .get (),
265+ shell.GetTaskRunners ().GetRasterTaskRunner ().get (),
266+ surface_producer_.value ());
267+ }
268+
259269 auto compositor_context =
260270 std::make_unique<flutter_runner::CompositorContext>(
261271 session_connection_.value (), surface_producer_.value (),
262272 legacy_external_view_embedder_);
263273 return std::make_unique<flutter::Rasterizer>(
264274 shell, std::move (compositor_context));
265275 } else {
276+ if (product_config.enable_shader_warmup ()) {
277+ FML_DCHECK (surface_producer_);
278+ WarmupSkps (shell.GetDartVM ()
279+ ->GetConcurrentMessageLoop ()
280+ ->GetTaskRunner ()
281+ .get (),
282+ shell.GetTaskRunners ().GetRasterTaskRunner ().get (),
283+ surface_producer_.value ());
284+ }
266285 return std::make_unique<flutter::Rasterizer>(shell);
267286 }
268287 };
@@ -641,9 +660,13 @@ void Engine::WarmupSkps(fml::BasicTaskRunner* concurrent_task_runner,
641660 fml::BasicTaskRunner* raster_task_runner,
642661 VulkanSurfaceProducer& surface_producer) {
643662 SkISize size = SkISize::Make (1024 , 600 );
644- auto skp_warmup_surface = surface_producer.ProduceOffscreenSurface (size);
663+ // We use a raw pointer here because we want to keep this alive until all gpu
664+ // work is done and the callbacks skia takes for this are function pointers
665+ // so we are unable to use a lambda that captures the smart pointer.
666+ SurfaceProducerSurface* skp_warmup_surface =
667+ surface_producer.ProduceOffscreenSurface (size).release ();
645668 if (!skp_warmup_surface) {
646- FML_LOG (ERROR) << " SkSurface::MakeRenderTarget returned null " ;
669+ FML_LOG (ERROR) << " Failed to create offscreen warmup surface " ;
647670 return ;
648671 }
649672
@@ -655,8 +678,17 @@ void Engine::WarmupSkps(fml::BasicTaskRunner* concurrent_task_runner,
655678 std::vector<std::unique_ptr<fml::Mapping>> skp_mappings =
656679 flutter::PersistentCache::GetCacheForProcess ()
657680 ->GetSkpsFromAssetManager ();
681+
682+ size_t total_size = 0 ;
683+ for (auto & mapping : skp_mappings) {
684+ total_size += mapping->GetSize ();
685+ }
686+
687+ FML_LOG (INFO) << " Shader warmup got " << skp_mappings.size ()
688+ << " skp's with a total size of " << total_size << " bytes" ;
689+
658690 std::vector<sk_sp<SkPicture>> pictures;
659- int i = 0 ;
691+ unsigned int i = 0 ;
660692 for (auto & mapping : skp_mappings) {
661693 std::unique_ptr<SkMemoryStream> stream =
662694 SkMemoryStream::MakeDirect (mapping->GetMapping (), mapping->GetSize ());
@@ -672,12 +704,28 @@ void Engine::WarmupSkps(fml::BasicTaskRunner* concurrent_task_runner,
672704
673705 // Tell raster task runner to warmup have the compositor
674706 // context warm up the newly deserialized picture
675- raster_task_runner->PostTask (
676- [skp_warmup_surface, picture, &surface_producer] {
677- TRACE_DURATION (" flutter" , " WarmupSkp" );
678- skp_warmup_surface->getCanvas ()->drawPicture (picture);
679- surface_producer.gr_context ()->flush ();
680- });
707+ raster_task_runner->PostTask ([skp_warmup_surface, picture,
708+ &surface_producer, i,
709+ count = skp_mappings.size ()] {
710+ TRACE_DURATION (" flutter" , " WarmupSkp" );
711+ skp_warmup_surface->GetSkiaSurface ()->getCanvas ()->drawPicture (picture);
712+
713+ if (i < count - 1 ) {
714+ // For all but the last skp we fire and forget
715+ surface_producer.gr_context ()->flushAndSubmit ();
716+ } else {
717+ // For the last skp we provide a callback that frees the warmup
718+ // surface
719+ struct GrFlushInfo flush_info;
720+ flush_info.fFinishedContext = skp_warmup_surface;
721+ flush_info.fFinishedProc = [](void * skp_warmup_surface) {
722+ delete static_cast <SurfaceProducerSurface*>(skp_warmup_surface);
723+ };
724+
725+ surface_producer.gr_context ()->flush (flush_info);
726+ surface_producer.gr_context ()->submit ();
727+ }
728+ });
681729 i++;
682730 }
683731 });
0 commit comments