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

Improve iOS PlatformViews to better handle thread merging. #16935

Merged
merged 30 commits into from
Apr 9, 2020

Conversation

cyanglaz
Copy link
Contributor

@cyanglaz cyanglaz commented Mar 4, 2020

This PR is a partial effort of enabling dynamic thread merging on iOS. flutter/flutter#23975

This PR mainly focuses on potential crashes after enabling thread merge. This PR DOES NOT enable thread merging and the behavior of iOS platform view and rasterizer should be the same as it is today after this. PR lands.

This PR includes:

  1. Postpone thread merging to the very end of the frame. Introduced a EndFrame method in the ExternalViewEmbedder; updated the code in FlutterPlatformViewsController to handle that change.
  2. Adding several main thread checks in the FlutterPlatformViewsController to help reproduce crashes related to running UIKit operations in background threads.
  3. Add some documentations and comments for certain related methods in the FlutterPlatformViewsController.
  4. Makes sure the [CATransaction commit] only runs on the main thread.

Edit:
ExternalViewEmbedder impls in ios_surface_gl and ios_surface_software are combined into ios_surface after this PR was put up. This PR has updated to reflect this change.

@auto-assign auto-assign bot requested a review from cbracken March 4, 2020 18:31
@cyanglaz cyanglaz requested review from amirh and removed request for cbracken March 4, 2020 18:31
@cyanglaz cyanglaz requested a review from iskakaushik March 4, 2020 18:31
@cyanglaz cyanglaz changed the title Fixes crashes in iOS dynamic thread merging. Improve iOS PlatformViews to better handle thread merging. Mar 13, 2020
@@ -250,6 +250,14 @@ class ExternalViewEmbedder {

virtual bool SubmitFrame(GrContext* context);

// Caller should make sure to call this after |SubmitFrame|.
Copy link
Contributor

Choose a reason for hiding this comment

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

This should only be called after |SubmitFrame| reads better.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@@ -250,6 +250,14 @@ class ExternalViewEmbedder {

virtual bool SubmitFrame(GrContext* context);

// Caller should make sure to call this after |SubmitFrame|.
// Embedder that implements this method to do additional tasks after
Copy link
Contributor

Choose a reason for hiding this comment

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

This method provides the embedder a way to do additional tasks after |SubmitFrame|.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@@ -250,6 +250,14 @@ class ExternalViewEmbedder {

virtual bool SubmitFrame(GrContext* context);

// Caller should make sure to call this after |SubmitFrame|.
// Embedder that implements this method to do additional tasks after
// |SubmitFrame|. One of such examples is threading merging on iOS.
Copy link
Contributor

Choose a reason for hiding this comment

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

For example on the iOS embedder, ...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

// Embedder that implements this method to do additional tasks after
// |SubmitFrame|. One of such examples is threading merging on iOS.
//
// After invoking this method, the current task on the TaskRunner should end
Copy link
Contributor

Choose a reason for hiding this comment

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

It will be useful to document why this is the case as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

changed the whole paragraph a little bit, could you take a look again?

@@ -184,8 +184,9 @@
if (gpu_thread_merger->IsMerged()) {
gpu_thread_merger->ExtendLeaseTo(kDefaultMergedLeaseDuration);
} else {
// Wait until |EndFrame| to perform thread merging.
Copy link
Contributor

Choose a reason for hiding this comment

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

to perform thread merging -> to merge the threads.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@@ -184,8 +184,9 @@
if (gpu_thread_merger->IsMerged()) {
gpu_thread_merger->ExtendLeaseTo(kDefaultMergedLeaseDuration);
} else {
// Wait until |EndFrame| to perform thread merging.
will_merge_threads_ = true;
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: merge_threads_

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@@ -368,6 +369,12 @@

bool FlutterPlatformViewsController::SubmitFrame(GrContext* gr_context,
std::shared_ptr<IOSContext> ios_context) {
if (will_merge_threads_) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Please add a comment explaining why these are cleared.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@@ -91,6 +91,8 @@ class FlutterPlatformViewsController {

void SetFrameSize(SkISize frame_size);

// Indicates that we don't compisite any platform views or overlays during this frame.
// Also reverts the composite_order_ to its original state at the begining of the frame.
Copy link
Contributor

Choose a reason for hiding this comment

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

composition_order_

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@@ -170,6 +177,8 @@ class FlutterPlatformViewsController {
void OnAcceptGesture(FlutterMethodCall* call, FlutterResult& result);
void OnRejectGesture(FlutterMethodCall* call, FlutterResult& result);

// Remove PlatformViews and Overlays that is in `active_composition_order_` but not
Copy link
Contributor

Choose a reason for hiding this comment

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

that are in, must run on platform thread.

Copy link
Contributor Author

@cyanglaz cyanglaz left a comment

Choose a reason for hiding this comment

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

@iskakaushik Updated based on your comments.

@@ -250,6 +250,14 @@ class ExternalViewEmbedder {

virtual bool SubmitFrame(GrContext* context);

// Caller should make sure to call this after |SubmitFrame|.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@@ -250,6 +250,14 @@ class ExternalViewEmbedder {

virtual bool SubmitFrame(GrContext* context);

// Caller should make sure to call this after |SubmitFrame|.
// Embedder that implements this method to do additional tasks after
// |SubmitFrame|. One of such examples is threading merging on iOS.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@@ -250,6 +250,14 @@ class ExternalViewEmbedder {

virtual bool SubmitFrame(GrContext* context);

// Caller should make sure to call this after |SubmitFrame|.
// Embedder that implements this method to do additional tasks after
Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

// Embedder that implements this method to do additional tasks after
// |SubmitFrame|. One of such examples is threading merging on iOS.
//
// After invoking this method, the current task on the TaskRunner should end
Copy link
Contributor Author

Choose a reason for hiding this comment

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

changed the whole paragraph a little bit, could you take a look again?

@@ -184,8 +184,9 @@
if (gpu_thread_merger->IsMerged()) {
gpu_thread_merger->ExtendLeaseTo(kDefaultMergedLeaseDuration);
} else {
// Wait until |EndFrame| to perform thread merging.
will_merge_threads_ = true;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@@ -184,8 +184,9 @@
if (gpu_thread_merger->IsMerged()) {
gpu_thread_merger->ExtendLeaseTo(kDefaultMergedLeaseDuration);
} else {
// Wait until |EndFrame| to perform thread merging.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@@ -368,6 +369,12 @@

bool FlutterPlatformViewsController::SubmitFrame(GrContext* gr_context,
std::shared_ptr<IOSContext> ios_context) {
if (will_merge_threads_) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@@ -91,6 +91,8 @@ class FlutterPlatformViewsController {

void SetFrameSize(SkISize frame_size);

// Indicates that we don't compisite any platform views or overlays during this frame.
// Also reverts the composite_order_ to its original state at the begining of the 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.

done

@blasten
Copy link

blasten commented Mar 27, 2020

@iskakaushik is there anything left in this PR that you'd like to address?

// A new frame on the platform thread starts immediately. If the GPU thread
// still has some task running, there could be two frames being rendered
// concurrently, which causes undefined behaviors.
virtual void EndFrame(fml::RefPtr<fml::GpuThreadMerger> gpu_thread_merger) {}
Copy link

@blasten blasten Mar 27, 2020

Choose a reason for hiding this comment

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

q: The description of this method seems similar to FinishFrame. Is it possible to have a single method for both?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

we currently only call EndFrame during thread merging process. It doesn't seem to be doing the same thing with we are doing in FinishFrame.

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 is used particularly in the thread merging scenario. FinishFrame is actually not the very end of the frame. But the EndFrame marks the very end of the frame.

@iskakaushik
Copy link
Contributor

@blasten Sorry, this got off my radar. I will take a look at this on Monday.

@iskakaushik
Copy link
Contributor

can we write a test for this change?

@cyanglaz cyanglaz added waiting for tree to go green This PR is approved and tested, but waiting for the tree to be green to land. and removed waiting for tree to go green This PR is approved and tested, but waiting for the tree to be green to land. labels Apr 8, 2020
@cyanglaz cyanglaz merged commit f6b8eda into flutter:master Apr 9, 2020
@cyanglaz cyanglaz deleted the thread_merging_crash branch April 9, 2020 00:33
cyanglaz pushed a commit that referenced this pull request Apr 9, 2020
cyanglaz pushed a commit that referenced this pull request Apr 9, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Apr 9, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Apr 9, 2020
cyanglaz pushed a commit to cyanglaz/engine that referenced this pull request Apr 9, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Apr 9, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Apr 9, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Apr 9, 2020
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Apr 10, 2020
goderbauer pushed a commit to goderbauer/engine that referenced this pull request Apr 16, 2020
goderbauer pushed a commit to goderbauer/engine that referenced this pull request Apr 16, 2020
@cyanglaz cyanglaz restored the thread_merging_crash branch April 28, 2020 20:42
cyanglaz pushed a commit that referenced this pull request May 1, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants