SKP based shader warmup (#20643)

This commit is contained in:
freiling 2020-11-04 23:19:02 -08:00 committed by GitHub
parent e66a720137
commit 3105db8ee8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 443 additions and 19 deletions

View File

@ -51,6 +51,24 @@ std::unique_ptr<fml::Mapping> AssetManager::GetAsMapping(
return nullptr;
}
// |AssetResolver|
std::vector<std::unique_ptr<fml::Mapping>> AssetManager::GetAsMappings(
const std::string& asset_pattern) const {
std::vector<std::unique_ptr<fml::Mapping>> mappings;
if (asset_pattern.size() == 0) {
return mappings;
}
TRACE_EVENT1("flutter", "AssetManager::GetAsMappings", "pattern",
asset_pattern.c_str());
for (const auto& resolver : resolvers_) {
auto resolver_mappings = resolver->GetAsMappings(asset_pattern);
mappings.insert(mappings.end(),
std::make_move_iterator(resolver_mappings.begin()),
std::make_move_iterator(resolver_mappings.end()));
}
return mappings;
}
// |AssetResolver|
bool AssetManager::IsValid() const {
return resolvers_.size() > 0;

View File

@ -37,6 +37,10 @@ class AssetManager final : public AssetResolver {
std::unique_ptr<fml::Mapping> GetAsMapping(
const std::string& asset_name) const override;
// |AssetResolver|
std::vector<std::unique_ptr<fml::Mapping>> GetAsMappings(
const std::string& asset_pattern) const override;
private:
std::deque<std::unique_ptr<AssetResolver>> resolvers_;

View File

@ -42,6 +42,13 @@ class AssetResolver {
[[nodiscard]] virtual std::unique_ptr<fml::Mapping> GetAsMapping(
const std::string& asset_name) const = 0;
// Same as GetAsMapping() but returns mappings for all files who's name
// matches |pattern|. Returns empty vector if no matching assets are found
[[nodiscard]] virtual std::vector<std::unique_ptr<fml::Mapping>>
GetAsMappings(const std::string& asset_pattern) const {
return {};
};
private:
FML_DISALLOW_COPY_AND_ASSIGN(AssetResolver);
};

View File

@ -4,6 +4,7 @@
#include "flutter/assets/directory_asset_bundle.h"
#include <regex>
#include <utility>
#include "flutter/fml/eintr_wrapper.h"
@ -53,4 +54,32 @@ std::unique_ptr<fml::Mapping> DirectoryAssetBundle::GetAsMapping(
return mapping;
}
std::vector<std::unique_ptr<fml::Mapping>> DirectoryAssetBundle::GetAsMappings(
const std::string& asset_pattern) const {
std::vector<std::unique_ptr<fml::Mapping>> mappings;
if (!is_valid_) {
FML_DLOG(WARNING) << "Asset bundle was not valid.";
return mappings;
}
std::regex asset_regex(asset_pattern);
fml::FileVisitor visitor = [&](const fml::UniqueFD& directory,
const std::string& filename) {
if (std::regex_match(filename, asset_regex)) {
auto mapping = std::make_unique<fml::FileMapping>(fml::OpenFile(
directory, filename.c_str(), false, fml::FilePermission::kRead));
if (mapping && mapping->IsValid()) {
mappings.push_back(std::move(mapping));
} else {
FML_LOG(ERROR) << "Mapping " << filename << " failed";
}
}
return true;
};
fml::VisitFilesRecursively(descriptor_, visitor);
return mappings;
}
} // namespace flutter

View File

@ -34,6 +34,10 @@ class DirectoryAssetBundle : public AssetResolver {
std::unique_ptr<fml::Mapping> GetAsMapping(
const std::string& asset_name) const override;
// |AssetResolver|
std::vector<std::unique_ptr<fml::Mapping>> GetAsMappings(
const std::string& asset_pattern) const override;
FML_DISALLOW_COPY_AND_ASSIGN(DirectoryAssetBundle);
};

View File

@ -12,6 +12,7 @@
#include "flutter/fml/closure.h"
#include "flutter/fml/macros.h"
#include "flutter/fml/task_runner.h"
namespace fml {
@ -58,13 +59,13 @@ class ConcurrentMessageLoop
FML_DISALLOW_COPY_AND_ASSIGN(ConcurrentMessageLoop);
};
class ConcurrentTaskRunner {
class ConcurrentTaskRunner : public BasicTaskRunner {
public:
ConcurrentTaskRunner(std::weak_ptr<ConcurrentMessageLoop> weak_loop);
~ConcurrentTaskRunner();
virtual ~ConcurrentTaskRunner();
void PostTask(const fml::closure& task);
void PostTask(const fml::closure& task) override;
private:
friend ConcurrentMessageLoop;

View File

@ -16,11 +16,17 @@ namespace fml {
class MessageLoopImpl;
class TaskRunner : public fml::RefCountedThreadSafe<TaskRunner> {
class BasicTaskRunner {
public:
virtual void PostTask(const fml::closure& task) = 0;
};
class TaskRunner : public fml::RefCountedThreadSafe<TaskRunner>,
public BasicTaskRunner {
public:
virtual ~TaskRunner();
virtual void PostTask(const fml::closure& task);
virtual void PostTask(const fml::closure& task) override;
virtual void PostTaskForTime(const fml::closure& task,
fml::TimePoint target_time);

View File

@ -391,4 +391,14 @@ void PersistentCache::SetAssetManager(std::shared_ptr<AssetManager> value) {
asset_manager_ = value;
}
std::vector<std::unique_ptr<fml::Mapping>>
PersistentCache::GetSkpsFromAssetManager() const {
if (!asset_manager_) {
FML_LOG(ERROR)
<< "PersistentCache::GetSkpsFromAssetManager: Asset manager not set!";
return std::vector<std::unique_ptr<fml::Mapping>>();
}
return asset_manager_->GetAsMappings(".*\\.skp$");
}
} // namespace flutter

View File

@ -74,6 +74,9 @@ class PersistentCache : public GrContextOptions::PersistentCache {
/// Load all the SkSL shader caches in the right directory.
std::vector<SkSLCache> LoadSkSLs();
// Return mappings for all skp's accessible through the AssetManager
std::vector<std::unique_ptr<fml::Mapping>> GetSkpsFromAssetManager() const;
/// Set the asset manager from which PersistentCache can load SkLSs. A nullptr
/// can be provided to clear the asset manager.
static void SetAssetManager(std::shared_ptr<AssetManager> value);

View File

@ -511,6 +511,7 @@ static sk_sp<SkData> ScreenshotLayerTreeAsPicture(
#if defined(OS_FUCHSIA)
SkSerialProcs procs = {0};
procs.fImageProc = SerializeImageWithoutData;
procs.fTypefaceProc = SerializeTypefaceWithoutData;
#else
SkSerialProcs procs = {0};
procs.fTypefaceProc = SerializeTypefaceWithData;

View File

@ -5,19 +5,26 @@
#include "flutter/fml/logging.h"
#include "include/core/SkImage.h"
#include "include/core/SkPicture.h"
#include "include/core/SkSerialProcs.h"
#include "include/core/SkStream.h"
#include "include/core/SkTypeface.h"
namespace flutter {
sk_sp<SkData> SerializeTypefaceWithoutData(SkTypeface* typeface, void* ctx) {
return typeface->serialize(SkTypeface::SerializeBehavior::kDontIncludeData);
return SkData::MakeEmpty();
}
sk_sp<SkData> SerializeTypefaceWithData(SkTypeface* typeface, void* ctx) {
return typeface->serialize(SkTypeface::SerializeBehavior::kDoIncludeData);
}
sk_sp<SkTypeface> DeserializeTypefaceWithoutData(const void* data,
size_t length,
void* ctx) {
return SkTypeface::MakeDefault();
}
struct ImageMetaData {
int32_t width;
int32_t height;

View File

@ -15,6 +15,9 @@ namespace flutter {
sk_sp<SkData> SerializeTypefaceWithoutData(SkTypeface* typeface, void* ctx);
sk_sp<SkData> SerializeTypefaceWithData(SkTypeface* typeface, void* ctx);
sk_sp<SkTypeface> DeserializeTypefaceWithoutData(const void* data,
size_t length,
void* ctx);
// Serializes only the metadata of the image and not the underlying pixel data.
sk_sp<SkData> SerializeImageWithoutData(SkImage* image, void* ctx);

View File

@ -10,6 +10,7 @@
#include <future>
#include <memory>
#include "assets/directory_asset_bundle.h"
#include "flutter/flow/layers/layer_tree.h"
#include "flutter/flow/layers/picture_layer.h"
#include "flutter/flow/layers/transform_layer.h"
@ -2208,5 +2209,72 @@ TEST_F(ShellTest, EngineRootIsolateLaunchesDontTakeVMDataSettings) {
isolate_create_latch.Wait();
}
TEST_F(ShellTest, AssetManagerSingle) {
fml::ScopedTemporaryDirectory asset_dir;
fml::UniqueFD asset_dir_fd = fml::OpenDirectory(
asset_dir.path().c_str(), false, fml::FilePermission::kRead);
std::string filename = "test_name";
std::string content = "test_content";
bool success = fml::WriteAtomically(asset_dir_fd, filename.c_str(),
fml::DataMapping(content));
ASSERT_TRUE(success);
AssetManager asset_manager;
asset_manager.PushBack(
std::make_unique<DirectoryAssetBundle>(std::move(asset_dir_fd), false));
auto mapping = asset_manager.GetAsMapping(filename);
ASSERT_TRUE(mapping != nullptr);
std::string result(reinterpret_cast<const char*>(mapping->GetMapping()),
mapping->GetSize());
ASSERT_TRUE(result == content);
}
TEST_F(ShellTest, AssetManagerMulti) {
fml::ScopedTemporaryDirectory asset_dir;
fml::UniqueFD asset_dir_fd = fml::OpenDirectory(
asset_dir.path().c_str(), false, fml::FilePermission::kRead);
std::vector<std::string> filenames = {
"good0",
"bad0",
"good1",
"bad1",
};
for (auto filename : filenames) {
bool success = fml::WriteAtomically(asset_dir_fd, filename.c_str(),
fml::DataMapping(filename));
ASSERT_TRUE(success);
}
AssetManager asset_manager;
asset_manager.PushBack(
std::make_unique<DirectoryAssetBundle>(std::move(asset_dir_fd), false));
auto mappings = asset_manager.GetAsMappings("(.*)");
ASSERT_TRUE(mappings.size() == 4);
std::vector<std::string> expected_results = {
"good0",
"good1",
};
mappings = asset_manager.GetAsMappings("(.*)good(.*)");
ASSERT_TRUE(mappings.size() == expected_results.size());
for (auto& mapping : mappings) {
std::string result(reinterpret_cast<const char*>(mapping->GetMapping()),
mapping->GetSize());
ASSERT_NE(
std::find(expected_results.begin(), expected_results.end(), result),
expected_results.end());
}
}
} // namespace testing
} // namespace flutter

View File

@ -19,15 +19,19 @@
#include "flutter/shell/common/switches.h"
#include "flutter/shell/version/version.h"
#include "flutter/testing/testing.h"
#include "include/core/SkFont.h"
#include "include/core/SkPicture.h"
#include "include/core/SkPictureRecorder.h"
#include "include/core/SkSerialProcs.h"
#include "include/core/SkTextBlob.h"
#if defined(OS_FUCHSIA)
#include "lib/sys/cpp/component_context.h"
#include "third_party/skia/include/ports/SkFontMgr_fuchsia.h"
namespace flutter {
namespace testing {
#if defined(OS_FUCHSIA)
static void WaitForIO(Shell* shell) {
std::promise<bool> io_task_finished;
shell->GetTaskRunners().GetIOTaskRunner()->PostTask(
@ -103,8 +107,13 @@ class SkpWarmupTest : public ShellTest {
SkDeserialProcs procs = {0};
procs.fImageProc = DeserializeImageWithoutData;
procs.fTypefaceProc = DeserializeTypefaceWithoutData;
sk_sp<SkPicture> picture =
SkPicture::MakeFromStream(stream.get(), &procs);
if (!picture) {
FML_LOG(ERROR) << "Failed to deserialize " << filename;
return true;
}
pictures.push_back(std::move(picture));
fd.reset();
}
@ -242,7 +251,51 @@ TEST_F(SkpWarmupTest, Image) {
TestWarmup(draw_size, builder);
}
#endif
// Re-enable once https://bugs.chromium.org/p/skia/issues/detail?id=10404
// is fixed and integrated, or a workaround is found.
TEST_F(SkpWarmupTest, DISABLED_Text) {
auto context = sys::ComponentContext::Create();
fuchsia::fonts::ProviderSyncPtr sync_font_provider;
context->svc()->Connect(sync_font_provider.NewRequest());
auto font_mgr = SkFontMgr_New_Fuchsia(std::move(sync_font_provider));
auto raw_typeface =
font_mgr->matchFamilyStyle(nullptr, SkFontStyle::Normal());
auto typeface = sk_sp<SkTypeface>(raw_typeface);
SkFont font(typeface, 12);
auto text_blob =
SkTextBlob::MakeFromString("test", font, SkTextEncoding::kUTF8);
SkISize draw_size =
SkISize::Make(text_blob->bounds().width(), text_blob->bounds().height());
// We reuse this builder to draw the same content sever times in this test
LayerTreeBuilder builder = [&draw_size, &text_blob,
this](std::shared_ptr<ContainerLayer> root) {
SkPictureRecorder recorder;
auto canvas =
recorder.beginRecording(draw_size.width(), draw_size.height());
auto color_space = SkColorSpace::MakeSRGB();
auto paint = SkPaint(SkColors::kWhite, color_space.get());
canvas->drawTextBlob(text_blob, draw_size.width() / 2,
draw_size.height() / 2, paint);
auto picture = recorder.finishRecordingAsPicture();
fml::RefPtr<SkiaUnrefQueue> queue = fml::MakeRefCounted<SkiaUnrefQueue>(
this->GetCurrentTaskRunner(), fml::TimeDelta::FromSeconds(0));
auto picture_layer = std::make_shared<PictureLayer>(
SkPoint::Make(0, 0), SkiaGPUObject<SkPicture>(picture, queue),
/* is_complex */ false,
/* will_change */ false);
root->Add(picture_layer);
};
TestWarmup(draw_size, builder);
}
} // namespace testing
} // namespace flutter
#endif // defined(OS_FUCHSIA)

View File

@ -447,6 +447,7 @@ executable("flutter_runner_unittests") {
"fuchsia_intl_unittest.cc",
"platform_view_unittest.cc",
"runner_unittest.cc",
"tests/engine_unittests.cc",
"tests/flutter_runner_product_configuration_unittests.cc",
"tests/vsync_recorder_unittests.cc",
"vsync_waiter_unittests.cc",
@ -458,6 +459,7 @@ executable("flutter_runner_unittests") {
# The use of these dependencies is temporary and will be moved behind the
# embedder API.
flutter_deps = [
"//flutter/assets:assets",
"//flutter/flow",
"//flutter/lib/ui",
"//flutter/shell/common",

View File

@ -145,7 +145,13 @@ CompositorContext::CompositorContext(
std::shared_ptr<flutter::SceneUpdateContext> scene_update_context)
: session_connection_(session_connection),
surface_producer_(surface_producer),
scene_update_context_(scene_update_context) {}
scene_update_context_(scene_update_context) {
SkISize size = SkISize::Make(1024, 600);
skp_warmup_surface_ = surface_producer_.ProduceOffscreenSurface(size);
if (!skp_warmup_surface_) {
FML_LOG(ERROR) << "SkSurface::MakeRenderTarget returned null";
}
}
CompositorContext::~CompositorContext() = default;
@ -164,4 +170,9 @@ CompositorContext::AcquireFrame(
session_connection_, surface_producer_, scene_update_context_);
}
void CompositorContext::WarmupSkp(const sk_sp<SkPicture> picture) {
skp_warmup_surface_->getCanvas()->drawPicture(picture);
surface_producer_.gr_context()->flush();
}
} // namespace flutter_runner

View File

@ -27,11 +27,13 @@ class CompositorContext final : public flutter::CompositorContext {
std::shared_ptr<flutter::SceneUpdateContext> scene_update_context);
~CompositorContext() override;
void WarmupSkp(sk_sp<SkPicture> picture);
private:
SessionConnection& session_connection_;
VulkanSurfaceProducer& surface_producer_;
std::shared_ptr<flutter::SceneUpdateContext> scene_update_context_;
sk_sp<SkSurface> skp_warmup_surface_;
// |flutter::CompositorContext|
std::unique_ptr<ScopedFrame> AcquireFrame(

View File

@ -14,16 +14,19 @@
#include "flutter/fml/synchronization/waitable_event.h"
#include "flutter/fml/task_runner.h"
#include "flutter/runtime/dart_vm_lifecycle.h"
#include "flutter/shell/common/persistent_cache.h"
#include "flutter/shell/common/rasterizer.h"
#include "flutter/shell/common/run_configuration.h"
#include "third_party/skia/include/ports/SkFontMgr_fuchsia.h"
#include "flutter/shell/common/serialization_callbacks.h"
#include "flutter_runner_product_configuration.h"
#include "fuchsia_external_view_embedder.h"
#include "fuchsia_intl.h"
#include "include/core/SkPicture.h"
#include "include/core/SkSerialProcs.h"
#include "platform_view.h"
#include "surface.h"
#include "task_runner_adapter.h"
#include "third_party/skia/include/ports/SkFontMgr_fuchsia.h"
#include "thread.h"
#if defined(LEGACY_FUCHSIA_EMBEDDER)
@ -258,7 +261,14 @@ Engine::Engine(Delegate& delegate,
}
};
#else
on_create_rasterizer = [](flutter::Shell& shell) {
on_create_rasterizer = [this, &product_config](flutter::Shell& shell) {
if (product_config.enable_shader_warmup()) {
FML_DCHECK(surface_producer_);
WarmupSkps(
shell.GetDartVM()->GetConcurrentMessageLoop()->GetTaskRunner().get(),
shell.GetTaskRunners().GetRasterTaskRunner().get(),
surface_producer_.value());
}
return std::make_unique<flutter::Rasterizer>(shell);
};
#endif
@ -625,4 +635,50 @@ void Engine::WriteProfileToTrace() const {
}
#endif // !defined(DART_PRODUCT)
void Engine::WarmupSkps(fml::BasicTaskRunner* concurrent_task_runner,
fml::BasicTaskRunner* raster_task_runner,
VulkanSurfaceProducer& surface_producer) {
SkISize size = SkISize::Make(1024, 600);
auto skp_warmup_surface = surface_producer.ProduceOffscreenSurface(size);
if (!skp_warmup_surface) {
FML_LOG(ERROR) << "SkSurface::MakeRenderTarget returned null";
return;
}
// tell concurrent task runner to deserialize all skps available from
// the asset manager
concurrent_task_runner->PostTask([&raster_task_runner, skp_warmup_surface,
&surface_producer]() {
TRACE_DURATION("flutter", "DeserializeSkps");
std::vector<std::unique_ptr<fml::Mapping>> skp_mappings =
flutter::PersistentCache::GetCacheForProcess()
->GetSkpsFromAssetManager();
std::vector<sk_sp<SkPicture>> pictures;
int i = 0;
for (auto& mapping : skp_mappings) {
std::unique_ptr<SkMemoryStream> stream =
SkMemoryStream::MakeDirect(mapping->GetMapping(), mapping->GetSize());
SkDeserialProcs procs = {0};
procs.fImageProc = flutter::DeserializeImageWithoutData;
procs.fTypefaceProc = flutter::DeserializeTypefaceWithoutData;
sk_sp<SkPicture> picture =
SkPicture::MakeFromStream(stream.get(), &procs);
if (!picture) {
FML_LOG(ERROR) << "Failed to deserialize picture " << i;
continue;
}
// Tell raster task runner to warmup have the compositor
// context warm up the newly deserialized picture
raster_task_runner->PostTask(
[skp_warmup_surface, picture, &surface_producer] {
TRACE_DURATION("flutter", "WarmupSkp");
skp_warmup_surface->getCanvas()->drawPicture(picture);
surface_producer.gr_context()->flush();
});
i++;
}
});
}
} // namespace flutter_runner

View File

@ -34,6 +34,10 @@
namespace flutter_runner {
namespace testing {
class EngineTest;
}
// Represents an instance of running Flutter engine along with the threads
// that host the same.
class Engine final {
@ -91,6 +95,10 @@ class Engine final {
fml::WeakPtrFactory<Engine> weak_factory_;
static void WarmupSkps(fml::BasicTaskRunner* concurrent_task_runner,
fml::BasicTaskRunner* raster_task_runner,
VulkanSurfaceProducer& surface_producer);
void OnMainIsolateStart();
void OnMainIsolateShutdown();
@ -105,6 +113,8 @@ class Engine final {
std::unique_ptr<flutter::Surface> CreateSurface();
friend class testing::EngineTest;
FML_DISALLOW_COPY_AND_ASSIGN(Engine);
};

View File

@ -33,6 +33,11 @@ FlutterRunnerProductConfiguration::FlutterRunnerProductConfiguration(
if (val.IsBool())
intercept_all_input_ = val.GetBool();
}
if (document.HasMember("enable_shader_warmup")) {
auto& val = document["enable_shader_warmup"];
if (val.IsBool())
enable_shader_warmup_ = val.GetBool();
}
#if defined(LEGACY_FUCHSIA_EMBEDDER)
if (document.HasMember("use_legacy_renderer")) {
auto& val = document["use_legacy_renderer"];

View File

@ -17,6 +17,7 @@ class FlutterRunnerProductConfiguration {
fml::TimeDelta get_vsync_offset() { return vsync_offset_; }
uint64_t get_max_frames_in_flight() { return max_frames_in_flight_; }
bool get_intercept_all_input() { return intercept_all_input_; }
bool enable_shader_warmup() { return enable_shader_warmup_; }
#if defined(LEGACY_FUCHSIA_EMBEDDER)
bool use_legacy_renderer() { return use_legacy_renderer_; }
#endif
@ -25,6 +26,7 @@ class FlutterRunnerProductConfiguration {
fml::TimeDelta vsync_offset_ = fml::TimeDelta::Zero();
uint64_t max_frames_in_flight_ = 3;
bool intercept_all_input_ = false;
bool enable_shader_warmup_ = false;
#if defined(LEGACY_FUCHSIA_EMBEDDER)
bool use_legacy_renderer_ = true;
#endif

View File

@ -8,12 +8,17 @@
"sandbox": {
"features": [
"deprecated-ambient-replace-as-executable",
"vulkan"
"vulkan",
"isolated-cache-storage",
"isolated-temp"
],
"services": [
"fuchsia.accessibility.semantics.SemanticsManager",
"fuchsia.intl.PropertyProvider",
"fuchsia.process.Launcher"
"fuchsia.process.Launcher",
"fuchsia.vulkan.loader.Loader",
"fuchsia.logger.LogSink",
"fuchsia.sysmem.Allocator"
]
}
}

View File

@ -0,0 +1,109 @@
// Copyright 2020 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <fuchsia/scenic/scheduling/cpp/fidl.h>
#include <fuchsia/ui/policy/cpp/fidl.h>
#include <fuchsia/ui/scenic/cpp/fidl.h>
#include <lib/async-loop/default.h>
#include <lib/sys/cpp/component_context.h>
#include "assets/directory_asset_bundle.h"
#include "flutter/fml/memory/ref_ptr.h"
#include "flutter/fml/message_loop_impl.h"
#include "flutter/fml/task_runner.h"
#include "flutter/shell/common/persistent_cache.h"
#include "flutter/shell/common/serialization_callbacks.h"
#include "flutter/shell/platform/fuchsia/flutter/logging.h"
#include "flutter/shell/platform/fuchsia/flutter/runner.h"
#include "flutter/shell/platform/fuchsia/flutter/session_connection.h"
#include "gtest/gtest.h"
#include "include/core/SkPicture.h"
#include "include/core/SkPictureRecorder.h"
#include "include/core/SkSerialProcs.h"
using namespace flutter_runner;
using namespace flutter;
namespace flutter_runner {
namespace testing {
class MockTaskRunner : public fml::BasicTaskRunner {
public:
MockTaskRunner() {}
virtual ~MockTaskRunner() {}
void PostTask(const fml::closure& task) override {
task_count_++;
task();
}
int GetTaskCount() { return task_count_; }
private:
int task_count_ = 0;
};
class EngineTest : public ::testing::Test {
public:
void WarmupSkps() {
// Have to create a message loop so default async dispatcher gets set,
// otherwise we segfault creating the VulkanSurfaceProducer
auto loop = fml::MessageLoopImpl::Create();
fuchsia::ui::scenic::SessionPtr session_ptr;
scenic::Session session(std::move(session_ptr));
VulkanSurfaceProducer surface_producer(&session);
Engine::WarmupSkps(&concurrent_task_runner_, &raster_task_runner_,
surface_producer);
}
protected:
MockTaskRunner concurrent_task_runner_;
MockTaskRunner raster_task_runner_;
};
TEST_F(EngineTest, SkpWarmup) {
SkISize draw_size = SkISize::Make(100, 100);
SkPictureRecorder recorder;
auto canvas = recorder.beginRecording(draw_size.width(), draw_size.height());
// adapted from https://fiddle.skia.org/c/@Canvas_drawLine
SkPaint paint;
paint.setColor(0xFF9a67be);
paint.setStrokeWidth(20);
canvas->drawLine(0, 0, draw_size.width(), draw_size.height(), paint);
canvas->drawLine(0, draw_size.height(), draw_size.width(), 0, paint);
sk_sp<SkPicture> picture = recorder.finishRecordingAsPicture();
SkSerialProcs procs = {0};
procs.fImageProc = SerializeImageWithoutData;
procs.fTypefaceProc = SerializeTypefaceWithoutData;
sk_sp<SkData> data = picture->serialize(&procs);
ASSERT_TRUE(data);
ASSERT_GT(data->size(), 0u);
fml::NonOwnedMapping mapping(data->bytes(), data->size());
fml::ScopedTemporaryDirectory asset_dir;
fml::UniqueFD asset_dir_fd = fml::OpenDirectory(
asset_dir.path().c_str(), false, fml::FilePermission::kRead);
bool success = fml::WriteAtomically(asset_dir_fd, "test.skp", mapping);
ASSERT_TRUE(success);
auto asset_manager = std::make_shared<AssetManager>();
asset_manager->PushBack(
std::make_unique<DirectoryAssetBundle>(std::move(asset_dir_fd), false));
PersistentCache::GetCacheForProcess()->SetAssetManager(asset_manager);
WarmupSkps();
EXPECT_EQ(concurrent_task_runner_.GetTaskCount(), 1);
EXPECT_EQ(raster_task_runner_.GetTaskCount(), 1);
}
} // namespace testing
} // namespace flutter_runner

View File

@ -26,6 +26,7 @@ class VulkanSurfacePool final {
~VulkanSurfacePool();
std::unique_ptr<VulkanSurface> CreateSurface(const SkISize& size);
std::unique_ptr<VulkanSurface> AcquireSurface(const SkISize& size);
void SubmitSurface(std::unique_ptr<SurfaceProducerSurface> surface);
@ -49,8 +50,6 @@ class VulkanSurfacePool final {
std::unique_ptr<VulkanSurface> GetCachedOrCreateSurface(const SkISize& size);
std::unique_ptr<VulkanSurface> CreateSurface(const SkISize& size);
void RecycleSurface(std::unique_ptr<VulkanSurface> surface);
void RecyclePendingSurface(uintptr_t surface_key);

View File

@ -271,4 +271,9 @@ void VulkanSurfaceProducer::SubmitSurface(
surface_pool_->SubmitSurface(std::move(surface));
}
sk_sp<SkSurface> VulkanSurfaceProducer::ProduceOffscreenSurface(
const SkISize& size) {
return surface_pool_->CreateSurface(size)->GetSkiaSurface();
}
} // namespace flutter_runner

View File

@ -35,13 +35,15 @@ class VulkanSurfaceProducer final : public SurfaceProducer,
std::unique_ptr<SurfaceProducerSurface> ProduceSurface(
const SkISize& size) override;
sk_sp<SkSurface> ProduceOffscreenSurface(const SkISize& size);
// |SurfaceProducer|
void SubmitSurface(std::unique_ptr<SurfaceProducerSurface> surface) override;
void OnSurfacesPresented(
std::vector<std::unique_ptr<SurfaceProducerSurface>> surfaces);
GrDirectContext* gr_context() { return context_.get(); }
GrDirectContext* gr_context() const { return context_.get(); }
private:
// VulkanProvider

View File

@ -19,7 +19,9 @@
"fuchsia.settings.Intl",
"fuchsia.sysmem.Allocator",
"fuchsia.tracing.provider.Registry",
"fuchsia.vulkan.loader.Loader"
"fuchsia.vulkan.loader.Loader",
"fuchsia.intl.PropertyProvider",
"fuchsia.fonts.Provider"
]
}
}