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

Use eglPresentationTimeANDROID to avoid bogging down the GPU #29727

Merged
merged 5 commits into from
Nov 19, 2021

Conversation

dnfield
Copy link
Contributor

@dnfield dnfield commented Nov 13, 2021

Fixes flutter/flutter#93352

Improves Android benchmarks on both Pixel 4 and a lower end Android Go device for 99th percentile and average raster times.

This works by telling the system compositor what timestamp we intended to show this frame for. This way, if we end up with a frame that gets submitted right at the beginning of a vsync and then a second frame submitted on the same vsync, the compositor will only try to show the second frame on the screen and save the GPU some work.

Without this, a situation like that results in an "avalanche" of calls where the GPU is behind the CPU and keeps delaying CPU work until we finally stop submitting frames. This can be observed as a lengthy dequeuBuffer in a systrace enabled trace, as shown in the linked issue. This avalanche is often triggered by a frame that does a shader compile through a couple vsyncs and then is followed by a bunch of very fast frames that take less than a vsync to render - the first of those fast frames gets delivered before the end of the vsync that the slow frame ended in.

We cannot implement this ourselves because we don't know how long the swap buffers call will take on the system side, and if we try to guess we can very well get it wrong.

I've filed issues to look into adding this for Vulkan and Metal, although we should also first take traces there to make sure it's warranted.

See also: https://android-developers.googleblog.com/2020/04/high-refresh-rate-rendering-on-android.html

}
if (!compositor_frame) {
return RasterStatus::kFailed;
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This file is much easier to review if you choose the hide whitespace option in GitHub.

Copy link
Contributor

Choose a reason for hiding this comment

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

After googling it, an easy way to do this is to just add ?w=1 to the URL of this page and it will disable it for just this one visit.

@CaseyHillers CaseyHillers changed the base branch from master to main November 15, 2021 17:35
@flutter-dashboard
Copy link

This pull request was opened against a branch other than master. Since Flutter pull requests should not normally be opened against branches other than master, I have changed the base to master. If this was intended, you may modify the base back to main. See the Release Process for information about how other branches get updated.

Reviewers: Use caution before merging pull requests to branches other than master, unless this is an intentional hotfix/cherrypick.

@flutter-dashboard flutter-dashboard bot changed the base branch from main to master November 15, 2021 17:35
@CaseyHillers CaseyHillers changed the base branch from master to main November 15, 2021 18:11
SurfaceFrame::SubmitInfo submit_info;
submit_info.frame_damage = damage.GetFrameDamage();
submit_info.buffer_damage = damage.GetBufferDamage();
submit_info.target_time = frame_timings_recorder.GetVsyncTargetTime();
Copy link
Contributor

Choose a reason for hiding this comment

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

Since we're now depending on GetVsyncTargetTime for something other than metrics, I think we'll need to update VsyncWaiter to always get the current Display refresh rate instead of caching it. https://github.com/flutter/engine/blob/main/shell/platform/android/io/flutter/view/VsyncWaiter.java#L39

On Android S and later, Display.getRefreshRate() returns the current display refresh rate, instead of the app maximum. https://developer.android.com/about/versions/12/reference/compat-framework-changes#display_info_nr_advanced_supported

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@jason-simmons FYI - since I think you recently changed this to not do that.

Copy link
Member

Choose a reason for hiding this comment

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

The call to getRefreshRate() was taking a significant amount of time on the platform thread in some cases (see flutter/flutter#90883)

Reintroducing that call may be risky if it needs to be done on every frame.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Do we know if those devices were susceptible when running on Android S?

I guess the problem here is that some devices will scale the refresh rate automatically/dynamically.

It might also be interesting to see if the same delays exist when using the NDK API instead.

Copy link
Member

Choose a reason for hiding this comment

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

The Huawei device referenced in flutter/flutter#90883 (comment) was running Android P

I don't know if Android S ensures better performance for getRefreshRate

Copy link
Contributor Author

Choose a reason for hiding this comment

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

#29800 Should resolve this.

@flar
Copy link
Contributor

flar commented Nov 15, 2021

I wonder if this will help with the condition seen here: flutter/flutter#75540

@dnfield
Copy link
Contributor Author

dnfield commented Nov 18, 2021

The vsync timing will be fixed by #29800, which will land before this one. This patch is ready for review.

Copy link
Contributor

@iskakaushik iskakaushik left a comment

Choose a reason for hiding this comment

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

LGTM

@dnfield dnfield changed the base branch from master to main November 19, 2021 17:29
@dnfield dnfield merged commit 88948de into flutter:main Nov 19, 2021
@dnfield dnfield deleted the presentation_time branch November 19, 2021 17:37
dnfield added a commit that referenced this pull request Dec 14, 2021
dnfield added a commit that referenced this pull request Dec 14, 2021
* Revert "Fix eglPresentationTimeANDROID is no effective (#30182)"

This reverts commit 5502a0a.

* Revert "Use eglPresentationTimeANDROID to avoid bogging down the GPU (#29727)"

This reverts commit 88948de.
iskakaushik added a commit to iskakaushik/engine that referenced this pull request Jun 7, 2022
Attempt to reland: flutter#29727

TODO:

1. This isn't right in the cases where the frame has been resubmitted.
2. This hasn't been wired for impeller yet.
iskakaushik added a commit to iskakaushik/engine that referenced this pull request Jun 7, 2022
Attempt to reland: flutter#29727

TODO:

1. This isn't right in the cases where the frame has been resubmitted.
2. This hasn't been wired for impeller yet.
iskakaushik added a commit that referenced this pull request Jun 8, 2022
houhuayong pushed a commit to houhuayong/engine that referenced this pull request Jun 21, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Use eglPresentationTimeANDROID
5 participants