Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wire up Metal shader precompilation from offline training runs. #25644

Merged

Conversation

chinmaygarde
Copy link
Member

This commit depends on Skia support for Metal SKSL precompilation.

When a new Metal onscreen context is acquired, the engine will attempt to load
shaders stored in the io.flutter.shaders.json file packaged in the Flutter
asset bundle. This file can be obtained via offline training runs.

This works very similarly to the OpenGL backend. However, in the OpenGL backend,
shell initialization waits for precompilation to be completed. On the other
hand, in the Metal backend, precompilation happens immediately after shell
initialization. This is in an attempt to parallelize SKSL precompilation with
Dart isolate and framework setup. While it may be possible to parallelize
precompilation of SKSLs in the future, they are processed serially today.

Support for testing shells (that hold the Skia persistent cache) using the Metal
backend did not exist and has been added in this patch. However, I don't believe
this testing is sufficient because it only verifies that SKSLs can be dumped and
subsequently reused with a Metal backed Shell. Importantly, it doesn't verify
where is shell setup this precompilation happens. For that, the persistent cache
interface will need to be reworked to better fit with the shell unittests. I
considered it out of scope and will followup with those test updates in a later
patch.

I have also made tracing of precompilation consistent with OpenGL and Metal (and
Vulkan when support for that is added). The
PersistentCache::PrecompileKnownSKSLs trace will summarize the number of SKSLs
being precompiled (it is a counter trace) and the time taken to precompile each.

Fixes flutter/flutter#79298.

These traces show that precompilation is functional and occurs during application launch.
OnRasterizeReady

This commit depends on [Skia support for Metal SKSL precompilation][1].

When a new Metal onscreen context is acquired, the engine will attempt to load
shaders stored in the `io.flutter.shaders.json` file packaged in the Flutter
asset bundle. This file can be [obtained via offline training runs][2].

This works very similarly to the OpenGL backend. However, in the OpenGL backend,
shell initialization waits for precompilation to be completed. On the other
hand, in the Metal backend, precompilation happens immediately after shell
initialization. This is in an attempt to parallelize SKSL precompilation with
Dart isolate and framework setup. While it may be possible to parallelize
precompilation of SKSLs in the future, they are processed serially today.

Support for testing shells (that hold the Skia persistent cache) using the Metal
backend did not exist and has been added in this patch. However, I don't believe
this testing is sufficient because it only verifies that SKSLs can be dumped and
subsequently reused with a Metal backed Shell. Importantly, it doesn't verify
where is shell setup this precompilation happens. For that, the persistent cache
interface will need to be reworked to better fit with the shell unittests. I
considered it out of scope and will followup with those test updates in a later
patch.

I have also made tracing of precompilation consistent with OpenGL and Metal (and
Vulkan when support for that is added). The
`PersistentCache::PrecompileKnownSKSLs` trace will summarize the number of SKSLs
being precompiled (it is a counter trace) and the time taken to precompile each.

Fixes flutter/flutter#79298.

[1]: https://bugs.chromium.org/p/skia/issues/detail?id=11392 [2]:
https://flutter.dev/docs/perf/rendering/shader#how-to-use-sksl-warmup
return 0;
}

if (known_sksls.empty()) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is harmless but redundant. The loop will do nothing if there are no shaders.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


//----------------------------------------------------------------------------
/// @brief Precompile SKSLs packaged with the application and gathered
/// during during previous runs in the given context.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: "during during"

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

TEST_F(ShellTest, CacheSkSLWorks) {
static void WaitForRaster(Shell* shell) {
std::promise<bool> raster_task_finished;
shell->GetTaskRunners().GetIOTaskRunner()->PostTask(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be GetRasterTaskRunner

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oof. Good catch. I added this to prevent a potential race.

}
return true;
};
fml::VisitFiles(dir.fd(), remove_visitor);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can fml::RemoveFilesInDirectory be used here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, you're right. I just copied the test right above this one which was probably written before the utility was available. Updated both.

@@ -155,6 +168,10 @@

// |Surface|
std::unique_ptr<GLContextResult> GPUSurfaceMetal::MakeRenderContextCurrent() {
// A context may be either be necessary to render to the surface or to snapshot an offscreen
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: "be either be"

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@@ -191,7 +192,35 @@ sk_sp<SkData> ParseBase64(const std::string& input) {
return data;
}

std::vector<PersistentCache::SkSLCache> PersistentCache::LoadSkSLs() {
size_t PersistentCache::PrecompileKnownSKSLs(GrDirectContext* context) const {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In Skia and elsewhere in the engine the spelling is "SkSL". I would prefer using that spelling in this PR for consistency.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Roger. I gsubbed all instances in //flutter for consistency.

Copy link
Member Author

@chinmaygarde chinmaygarde left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed all comments. PTAL. The presubmit failures were because I had assumed that GL emulation was available everywhere. This is not the case of Fuchsia. Fixed licenses which seem to be including test files as well 🤷🏽 .

@@ -191,7 +192,35 @@ sk_sp<SkData> ParseBase64(const std::string& input) {
return data;
}

std::vector<PersistentCache::SkSLCache> PersistentCache::LoadSkSLs() {
size_t PersistentCache::PrecompileKnownSKSLs(GrDirectContext* context) const {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Roger. I gsubbed all instances in //flutter for consistency.

return 0;
}

if (known_sksls.empty()) {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


//----------------------------------------------------------------------------
/// @brief Precompile SKSLs packaged with the application and gathered
/// during during previous runs in the given context.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

TEST_F(ShellTest, CacheSkSLWorks) {
static void WaitForRaster(Shell* shell) {
std::promise<bool> raster_task_finished;
shell->GetTaskRunners().GetIOTaskRunner()->PostTask(
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oof. Good catch. I added this to prevent a potential race.

}
return true;
};
fml::VisitFiles(dir.fd(), remove_visitor);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, you're right. I just copied the test right above this one which was probably written before the utility was available. Updated both.

@@ -155,6 +168,10 @@

// |Surface|
std::unique_ptr<GLContextResult> GPUSurfaceMetal::MakeRenderContextCurrent() {
// A context may be either be necessary to render to the surface or to snapshot an offscreen
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@chinmaygarde chinmaygarde added the waiting for tree to go green This PR is approved and tested, but waiting for the tree to be green to land. label Apr 19, 2021
@fluttergithubbot fluttergithubbot merged commit 7802d58 into flutter:master Apr 19, 2021
@chinmaygarde chinmaygarde deleted the mtl_sksl_offline_training branch April 19, 2021 23:25
@acoutts
Copy link

acoutts commented Apr 19, 2021

@chinmaygarde to use this we just need to use the same as under OpenGL with --cache-sksl and --bundle-sksl-path ?

@chinmaygarde
Copy link
Member Author

Right. The workflow is identical.

@acoutts
Copy link

acoutts commented Apr 20, 2021

Thanks @chinmaygarde - just to confirm, the latest master has it?

Flutter 2.2.0-11.0.pre.168 • channel master • https://github.com/flutter/flutter.git
Framework • revision ecbea9a9d5 (4 hours ago) • 2021-04-20 03:44:04 +0530
Engine • revision 60f12daf85
Tools • Dart 2.14.0 (build 2.14.0-8.0.dev)

@zanderso
Copy link
Member

@acoutts, @chinmaygarde's flutter/engine commit is still making its way into flutter/flutter master. It's not there yet. flutter/flutter#80769 looks like it will succeed when the flutter/flutter tree turns green.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cla: yes waiting for tree to go green This PR is approved and tested, but waiting for the tree to be green to land.
Projects
None yet
5 participants