Skip to content

Commit 062cbd8

Browse files
authored
Freiling warmup memory (flutter#22984)
* [fuchsia] enable boot time shader warmup even when LEGACY_FUCHSIA_EMBEDDER is defined * [fuchsia] decouple shader warmup from embedder api * [fuchsia] change warmup context flush() to flushAndSubmit() to reduce memory footprint of warmup * [fuchsia] Fix GPU resource lifecycle issue with shader warmup This fixes an issue with the shader warmup where gpu resources could end up deleted before the gpu work that needed them was complete, leading to GPU page faults. This was because although the sk_sp<SkSurface> will normally keep resources alive throughout its lifetime, the SurfaceProducerSurface will call VkDestroyMemory on the memory backing the SkSurface when it is deleted, even if the SkSurface wrapping that VkMemory is still alive. This change also deletes some related but unused code from CompositorContext that I noticed while refactoring.
1 parent 7647fdb commit 062cbd8

File tree

5 files changed

+64
-28
lines changed

5 files changed

+64
-28
lines changed

shell/platform/fuchsia/flutter/compositor_context.cc

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -154,13 +154,7 @@ CompositorContext::CompositorContext(
154154
std::shared_ptr<flutter::SceneUpdateContext> scene_update_context)
155155
: session_connection_(session_connection),
156156
surface_producer_(surface_producer),
157-
scene_update_context_(scene_update_context) {
158-
SkISize size = SkISize::Make(1024, 600);
159-
skp_warmup_surface_ = surface_producer_.ProduceOffscreenSurface(size);
160-
if (!skp_warmup_surface_) {
161-
FML_LOG(ERROR) << "SkSurface::MakeRenderTarget returned null";
162-
}
163-
}
157+
scene_update_context_(scene_update_context) {}
164158

165159
CompositorContext::~CompositorContext() = default;
166160

@@ -179,9 +173,4 @@ CompositorContext::AcquireFrame(
179173
session_connection_, surface_producer_, scene_update_context_);
180174
}
181175

182-
void CompositorContext::WarmupSkp(const sk_sp<SkPicture> picture) {
183-
skp_warmup_surface_->getCanvas()->drawPicture(picture);
184-
surface_producer_.gr_context()->flush();
185-
}
186-
187176
} // namespace flutter_runner

shell/platform/fuchsia/flutter/compositor_context.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,11 @@ class CompositorContext final : public flutter::CompositorContext {
2727
std::shared_ptr<flutter::SceneUpdateContext> scene_update_context);
2828

2929
~CompositorContext() override;
30-
void WarmupSkp(sk_sp<SkPicture> picture);
3130

3231
private:
3332
SessionConnection& session_connection_;
3433
VulkanSurfaceProducer& surface_producer_;
3534
std::shared_ptr<flutter::SceneUpdateContext> scene_update_context_;
36-
sk_sp<SkSurface> skp_warmup_surface_;
3735

3836
// |flutter::CompositorContext|
3937
std::unique_ptr<ScopedFrame> AcquireFrame(

shell/platform/fuchsia/flutter/engine.cc

Lines changed: 58 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -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
});

shell/platform/fuchsia/flutter/vulkan_surface_producer.cc

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -271,9 +271,9 @@ void VulkanSurfaceProducer::SubmitSurface(
271271
surface_pool_->SubmitSurface(std::move(surface));
272272
}
273273

274-
sk_sp<SkSurface> VulkanSurfaceProducer::ProduceOffscreenSurface(
275-
const SkISize& size) {
276-
return surface_pool_->CreateSurface(size)->GetSkiaSurface();
274+
std::unique_ptr<SurfaceProducerSurface>
275+
VulkanSurfaceProducer::ProduceOffscreenSurface(const SkISize& size) {
276+
return surface_pool_->CreateSurface(size);
277277
}
278278

279279
} // namespace flutter_runner

shell/platform/fuchsia/flutter/vulkan_surface_producer.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ class VulkanSurfaceProducer final : public SurfaceProducer,
3535
std::unique_ptr<SurfaceProducerSurface> ProduceSurface(
3636
const SkISize& size) override;
3737

38-
sk_sp<SkSurface> ProduceOffscreenSurface(const SkISize& size);
38+
std::unique_ptr<SurfaceProducerSurface> ProduceOffscreenSurface(
39+
const SkISize& size);
3940

4041
// |SurfaceProducer|
4142
void SubmitSurface(std::unique_ptr<SurfaceProducerSurface> surface) override;

0 commit comments

Comments
 (0)