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

Commit 85b7ce9

Browse files
committed
[fuchsia] implement SKP based shader warmup
Make Engine load all .skp files from persistent cache and draw them on an offscreen surface to warm up shaders.
1 parent f9300f2 commit 85b7ce9

File tree

6 files changed

+110
-4
lines changed

6 files changed

+110
-4
lines changed

shell/platform/fuchsia/flutter/compositor_context.cc

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,13 @@ CompositorContext::CompositorContext(
145145
flutter::SceneUpdateContext& scene_update_context)
146146
: session_connection_(session_connection),
147147
surface_producer_(surface_producer),
148-
scene_update_context_(scene_update_context) {}
148+
scene_update_context_(scene_update_context) {
149+
SkISize size = SkISize::Make(1024, 600);
150+
skp_warmup_surface_ = surface_producer_.ProduceOffscreenSurface(size);
151+
if (!skp_warmup_surface_) {
152+
FML_LOG(ERROR) << "SkSurface::MakeRenderTarget returned null";
153+
}
154+
}
149155

150156
CompositorContext::~CompositorContext() = default;
151157

@@ -164,4 +170,9 @@ CompositorContext::AcquireFrame(
164170
session_connection_, surface_producer_, scene_update_context_);
165171
}
166172

173+
void CompositorContext::WarmupSkp(const sk_sp<SkPicture> picture) {
174+
skp_warmup_surface_->getCanvas()->drawPicture(picture);
175+
surface_producer_.gr_context()->flush();
176+
}
177+
167178
} // namespace flutter_runner

shell/platform/fuchsia/flutter/compositor_context.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,14 @@ class CompositorContext final : public flutter::CompositorContext {
2626
flutter::SceneUpdateContext& scene_update_context);
2727

2828
~CompositorContext() override;
29+
void WarmupSkp(sk_sp<SkPicture> picture);
2930

3031
private:
3132
SessionConnection& session_connection_;
3233
VulkanSurfaceProducer& surface_producer_;
3334
flutter::SceneUpdateContext& scene_update_context_;
35+
sk_sp<SkSurface> skp_warmup_surface_;
36+
3437

3538
// |flutter::CompositorContext|
3639
std::unique_ptr<ScopedFrame> AcquireFrame(

shell/platform/fuchsia/flutter/engine.cc

Lines changed: 86 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,16 @@
1313
#include "flutter/fml/synchronization/waitable_event.h"
1414
#include "flutter/fml/task_runner.h"
1515
#include "flutter/runtime/dart_vm_lifecycle.h"
16+
#include "flutter/shell/common/persistent_cache.h"
1617
#include "flutter/shell/common/rasterizer.h"
1718
#include "flutter/shell/common/run_configuration.h"
1819
#include "third_party/skia/include/ports/SkFontMgr_fuchsia.h"
19-
20+
#include "flutter/shell/common/serialization_callbacks.h"
2021
#include "flutter_runner_product_configuration.h"
2122
#include "fuchsia_external_view_embedder.h"
2223
#include "fuchsia_intl.h"
24+
#include "include/core/SkPicture.h"
25+
#include "include/core/SkSerialProcs.h"
2326
#include "platform_view.h"
2427
#include "surface.h"
2528
#include "task_runner_adapter.h"
@@ -237,14 +240,95 @@ Engine::Engine(Delegate& delegate,
237240
std::make_unique<flutter_runner::CompositorContext>(
238241
session_connection_.value(), surface_producer_.value(),
239242
legacy_external_view_embedder_.value());
243+
244+
// tell concurrent task runner to deserialize all skps available from
245+
// the asset manager
246+
shell.GetDartVM()->GetConcurrentMessageLoop()->GetTaskRunner()->PostTask([raster_task_runner =
247+
shell.GetTaskRunners().GetRasterTaskRunner(),
248+
compositor_context = compositor_context.get()]() {
249+
TRACE_DURATION("flutter", "DeserializeSkps");
250+
std::vector<std::unique_ptr<fml::Mapping>> skp_mappings =
251+
flutter::PersistentCache::GetCacheForProcess()
252+
->GetSkpsFromAssetManager();
253+
std::vector<sk_sp<SkPicture>> pictures;
254+
int i = 0;
255+
for (auto& mapping : skp_mappings) {
256+
257+
std::unique_ptr<SkMemoryStream> stream =
258+
SkMemoryStream::MakeDirect(mapping->GetMapping(),
259+
mapping->GetSize());
260+
SkDeserialProcs procs = {0};
261+
procs.fImageProc = flutter::DeserializeImageWithoutData;
262+
procs.fTypefaceProc = flutter::DeserializeTypefaceWithoutData;
263+
sk_sp<SkPicture> picture =
264+
SkPicture::MakeFromStream(stream.get(), &procs);
265+
if (!picture) {
266+
FML_LOG(ERROR) << "Failed to deserialize picture " << i;
267+
continue;
268+
}
269+
270+
// Tell raster task runner to warmup have the compositor
271+
// context warm up the newly deserialized picture
272+
raster_task_runner->PostTask([compositor_context, picture] {
273+
TRACE_DURATION("flutter", "WarmupSkp");
274+
compositor_context->WarmupSkp(picture);
275+
});
276+
i++;
277+
}
278+
});
279+
240280
return std::make_unique<flutter::Rasterizer>(
241281
shell, std::move(compositor_context));
242282
} else {
243283
return std::make_unique<flutter::Rasterizer>(shell);
244284
}
245285
};
246286
#else
247-
on_create_rasterizer = [](flutter::Shell& shell) {
287+
on_create_rasterizer = [this](flutter::Shell& shell) {
288+
FML_DCHECK(surface_producer_);
289+
290+
SkISize size = SkISize::Make(1024, 600);
291+
auto skp_warmup_surface = surface_producer_->ProduceOffscreenSurface(size);
292+
if (!skp_warmup_surface) {
293+
FML_LOG(ERROR) << "SkSurface::MakeRenderTarget returned null";
294+
return std::make_unique<flutter::Rasterizer>(shell);
295+
}
296+
297+
// tell concurrent task runner to deserialize all skps available from
298+
// the asset manager
299+
shell.GetDartVM()->GetConcurrentMessageLoop()->GetTaskRunner()->PostTask([raster_task_runner =
300+
shell.GetTaskRunners().GetRasterTaskRunner(), skp_warmup_surface, this]() {
301+
TRACE_DURATION("flutter", "DeserializeSkps");
302+
std::vector<std::unique_ptr<fml::Mapping>> skp_mappings =
303+
flutter::PersistentCache::GetCacheForProcess()
304+
->GetSkpsFromAssetManager();
305+
std::vector<sk_sp<SkPicture>> pictures;
306+
int i = 0;
307+
for (auto& mapping : skp_mappings) {
308+
std::unique_ptr<SkMemoryStream> stream =
309+
SkMemoryStream::MakeDirect(mapping->GetMapping(),
310+
mapping->GetSize());
311+
SkDeserialProcs procs = {0};
312+
procs.fImageProc = flutter::DeserializeImageWithoutData;
313+
procs.fTypefaceProc = flutter::DeserializeTypefaceWithoutData;
314+
sk_sp<SkPicture> picture =
315+
SkPicture::MakeFromStream(stream.get(), &procs);
316+
if (!picture) {
317+
FML_LOG(ERROR) << "Failed to deserialize picture " << i;
318+
continue;
319+
}
320+
321+
// Tell raster task runner to warmup have the compositor
322+
// context warm up the newly deserialized picture
323+
raster_task_runner->PostTask([skp_warmup_surface, picture, this] {
324+
TRACE_DURATION("flutter", "WarmupSkp");
325+
skp_warmup_surface->getCanvas()->drawPicture(picture);
326+
surface_producer_->gr_context()->flush();
327+
});
328+
i++;
329+
}
330+
});
331+
248332
return std::make_unique<flutter::Rasterizer>(shell);
249333
};
250334
#endif

shell/platform/fuchsia/flutter/vulkan_surface_pool.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ class VulkanSurfacePool final {
2626

2727
~VulkanSurfacePool();
2828

29+
std::unique_ptr<VulkanSurface> CreateSurface(const SkISize& size);
2930
std::unique_ptr<VulkanSurface> AcquireSurface(const SkISize& size);
3031

3132
void SubmitSurface(std::unique_ptr<SurfaceProducerSurface> surface);
@@ -49,7 +50,6 @@ class VulkanSurfacePool final {
4950

5051
std::unique_ptr<VulkanSurface> GetCachedOrCreateSurface(const SkISize& size);
5152

52-
std::unique_ptr<VulkanSurface> CreateSurface(const SkISize& size);
5353

5454
void RecycleSurface(std::unique_ptr<VulkanSurface> surface);
5555

shell/platform/fuchsia/flutter/vulkan_surface_producer.cc

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

274+
sk_sp<SkSurface> VulkanSurfaceProducer::ProduceOffscreenSurface(const SkISize& size){
275+
return surface_pool_->CreateSurface(size)->GetSkiaSurface();
276+
}
277+
278+
274279
} // namespace flutter_runner

shell/platform/fuchsia/flutter/vulkan_surface_producer.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ class VulkanSurfaceProducer final : public SurfaceProducer,
3434
// |SurfaceProducer|
3535
std::unique_ptr<SurfaceProducerSurface> ProduceSurface(
3636
const SkISize& size) override;
37+
38+
sk_sp<SkSurface> ProduceOffscreenSurface(const SkISize& size);
39+
3740

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

0 commit comments

Comments
 (0)