-
Notifications
You must be signed in to change notification settings - Fork 6k
[Impeller] Update CAMetalLayer to be opaque #45994
Conversation
|
It looks like this pull request may not have tests. Please make sure to add tests before merging. If you need an exemption to this rule, contact Hixie or stuartmorgan on the #hackers channel in Chat (don't just cc them here, they won't see it! Use Discord!). If you are not sure if you need tests, consider this rule of thumb: the purpose of a test is to make sure someone doesn't accidentally revert the fix. Ask yourself, is there anything in your PR that you feel it is important we not accidentally revert back to how it was before your fix? Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing. |
| } else { | ||
| [command_buffer presentDrawable:drawable_]; | ||
| [command_buffer commit]; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be safe if we're not presenting with transaction, but needs more testing from me.
| // disable opaque, which on full screen flutter apps removes the direct to display | ||
| // optimization. This can increase presentation time by a frame interval, which | ||
| // is problematic on high frame rate devices. | ||
| if (!opaque) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@luckysmg , I found that if we set the background color to any value, it resets the value of layer.opaque. If you have a fullscreen flutter view and opaque is true, then we get a direct to display optimization and the presentation delay decreases from ~21ms to ~14ms, which is particularly important for high frame rate devices.
See some findings in flutter/flutter#134959
How are you using a FlutterView? Is it an add2app case where it is not the only view in the scene?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. We will change the layer's opaque to make the flutter view to be transparent and present it. The scene is that the new page is the transparent page, and it is presented on current page to do some thing like modal bottom sheet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If !opaque and set a white color, will it make the FlutterView not transparent?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ahh ok. Right now the problem is that we're unconditionally setting this clear color here. But setting the background color resets the value of opaque to NO, even if we requested it to be YES. So I think as long as your code is setting opaque = NO, this should keep working for you?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems not working... Here init with delegate is too early to set bg color to white.
If we need the view is transparent, we will set the opaque to NO and don't set bg color(in above link's code)
Before this patch: the result FlutterView is will be not opaque and with clear color, so it will be transparent ✅
After this patch: the result FlutterView is will be not opaque and with white color, so it will not be transparent ❌
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So your code is starting out with opaque = YES, then you're setting it to opaque = NO later? I'm not really familiar enough with flutter_boost to follow the rendering paths there. I can change this so that if you later set opaque = NO, then we also set the background color to the clearColor?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can change this so that if you later set opaque = NO, then we also set the background color to the clearColor?
I think this can work. But I m not sure this is good or not... Because this has a implicit operation: Change opaquealso change the bg color. Maybe sometimes will confusing the developer..
Edited: For me this is good ^_^
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah good point. I need to test if setting opaque after we set the background color also resets the background color too. If not, maybe I just change the order and leave this as is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
^_^
| // Note: this setting improves the performance of the "CPU TO Display Latency" metric in | ||
| // metal system trace. On high frame rate devices, this reduces the time we spend waiting | ||
| // for drawable availibility. | ||
| layer.opaque = YES; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Emm If we set this opaque=YES, means our the change to opaque is invalid? Since this will be called every frame.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll remove this
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just testing 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah ^_^
| layer.allowsGroupOpacity = YES; | ||
| layer.contentsScale = screenScale; | ||
| layer.rasterizationScale = screenScale; | ||
| layer.framebufferOnly = flutter::Settings::kSurfaceDataAccessible ? NO : YES; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This value should match what we set in
| layer.framebufferOnly = NO; |
|
Have a locally test for current patch. The constant junk is regression. I think the patch will also impact device not on iOS16.6. 😭 normal.video.mp4 |
|
Are you setting your FlutterViews opaque to YES or are you relying on the side effect of the bgcolor setting to make it opaque? |
|
I wouldn't consider this a fix for 16.6, the fix for that is to update to 17. But this does help, and fixes a bug since right now we're ignoring the opaque property entirely |
|
I test current patch with a pure flutter example without add to app. I didn't change any code of flutter view manually |
|
Can you run metal system trace and share a screenshot of the LCD category? For me, this is showing ~8ms faster presentations with this change. |
|
Will have a check later |
|
Tested on iPhone 13Pro iOS16.6.1 |
|
I'm testing on 17, but even on 16.6 I don't see this causing regressions - if anything its stabilizing things and I'm seeing more throughput. But event with a fast app we'll always hit a point where we're limited by drawables, given that there are only 3. I'm not sure what to make of this right now. |
|
If this is the case, then I suspect that setting the background color to the clearColor in #39359 fixed things for you by way of reseting the opaque bit. But I'm not sure why that would improve performance, since that seems to disable direct to display. I'm not sure if we use that opaque bit elsewhere, but we might be in a bit of an inconsistent state because while the layer is no opaque NO, the viewcontroller things opaque is YES 🤔 |
|
Yes. Confusing..... I will have a recheck to check whether my code applying your patch is correct. |
|
You might also try patching in a change that remove the backgroundColor but makes the default opaque to NO, to see if it has consistent performance. That should verify if it is the opaque field or the background color that is helping your case. |
|
Have a retest.
The screen will have jitter, but behavior is different from 1 point. I think this is because my iPhone is 16.6, I think maybe this code have no jitter on other version of iOS, but I have no other version of high FPS iPhone ... Maybe I will go to find one to take a look later |
|
@jonahwilliams I have a project to fire on later, not sure how long to have next response.. (just ensure you are not waiting for my resp because it is mid night in your time haha ^_^) |
|
No worries, I'm marking this as a draft for now while I investigate other things! |
|
@jonahwilliams I retest using iPhone13 Pro Max on iOS 16.0
Will regress the constant junk issue fixed in #39359
The app is smooth without any junk. Also I see the CALayer's |
|
OK, I think we can work with this. I suspect this explains why setting the background color improved performance then, because we were defaulting to Opaque = YES, and then changing the color reset it to NO? |
|
I'll need to do some follow ups and figure out what the official story is on Layer.opaque. |
Yes. I think so.. |
|
Sorry to ping on this again @luckysmg , but what is the CPU to display latency look like if you don't have this change patched in? |
|
I think without this change, it is the same in |
|
Makes sense, no worries. Still researching this 💻 🧑🔬 ! |
|
Closing as this seems to be a dead end. |


this setting improves the performance of the "CPU TO Display Latency" metric in metal system trace. On high frame rate devices, this reduces the time we spend waiting for drawable availibility. This only applies if the CAMetalLayer is fullscreen, as it allows a direct to display optimization that reduces "CPU TO Display Latency" from about 21 ms down to 14ms.
Xref: flutter/flutter#134959