-
Notifications
You must be signed in to change notification settings - Fork 5.9k
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
Dynamically determine whether to use offscreen surface based on need #13976
Conversation
Notes to self - to be tested:
|
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.
Exciting and a very necessary optimization!
I was wondering why calculating if the tree reads from the surface could not be done in the preroll. I suppose thats because the preroll happens after the surface frame has been acquired (please correct me if I am wrong). But there should be a reason the preroll needs a surface frame. If we moved it to be before the frame was acquired, could this be moved into the preroll?
BTW, testing this may be a whole lot easier with the patch under review that greatly fleshes out the Flow test harness #13949.
That is correct, and I alluded to that in the main description. Determining how to reorder those basic frame-pumping methods (Surface::AcquireFrame vs Layer::PreRoll) seemed outside the scope of this fix. And indeed just worrying about that issue had been keeping me from realizing and trying this slimmer version until now as I wasn't yet familiar enough with the engine to perform that kind of surgery. This approach, which can all happen during the scene building phase, allows us to get to 75-90% on the solution (depending on how much the caveats water down its effectiveness) without having to reorder the way that frames are pumped. I also think I've engineered it in a way that it can naturally flow into a more dynamic form that will let us determine the surface type after PreRoll once someone figures out how to move AcquireSurface to after PreRoll. |
Testing on the Gallery example app in the flutter framework I can see the offscreen come and go depending on whether I am viewing a Cupertino example. Most of the app is written in Material, but there is a Cupertino section. The list of Cupertino widgets is also shown in a Material list, but if you click on, say, the first item in the list (Alerts) you are taken to a page implemented in a Cupertino Page widget and you can see the offscreen show up in the observatory until you leave the Cupertino page. This is due to some of the Cupertino widgets installing a BackdropFilter widget automatically. You can tell if the offscreen is there by zooming in on the observatory. You will be looking for 2 or 3 boxes under the PipelineConsume box in the Pipeline Item section. You should always see a "LayerTree::Paint" event box followed by an "SkCanvas::Flush" event. If we are painting to an offscreen surface then you should also see a "CopyTextureOnscreen" event between them. If that event doesn't happen between the two, then we are rendering directly to the screen. |
Some data from the simple LinearProgressIndicator app.
Source for the app:
|
Document new fields and methods.
Here are the summaries from two runs of the backdrop_filter_perf benchmark. The difference in average frame build time was 3us, about .5%.
|
155eb4b
to
2fd78cc
Compare
Added a BackdropFilter flag test in the unit tests.
Would be good to have some correctness tests (tests that verify we're outputting the right pixels) in dynamic situations (where we're dynamically changing the scene from one which can benefit from this optimization to one that can't and back again). In general, this seems fine, with the caveat that I am not very familiar with this code. |
Theoretically true, but the interactions don't change what we render, just the type of drawable chosen. None of our code really makes any different choices as a result and we have plenty of cases of using an offscreen to perform rendering that we are staking on Skia's reputation will be identical to the screen. Isn't this essentially covered by the many golden tests we have already in the system which are all based on iOS rendering to an offscreen previously and now those same golden image tests will be rendering to the screen directly? If there is a golden image failure then we would essentially have our answer. Or am I misunderstanding the suggestion? |
Here's a quick comment on golden test and iOS (I didn't look into the details of this discussion): all our current golden tests are using software backend, and are running on Linux instead of iOS. Hence golden tests probably aren't guarding the changes in this PR. |
Wouldn't that also mean that they can't be used to test the changes in the PR in the first place, as was the suggestion? |
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.
LGTM. Thanks for the great work! Now let's wait for merging, rolling, and seeing the CPU/GPU usage metrics to drop down!
Also, currently I don't think that we have a device lab benchmark that covers the BackdropFilter after saveLayer optimization. It might be nice to add a test to verify it, and make sure that no one would accidentally break this optimization in the future (created issue flutter/flutter#45731).
Correct, I don't think that we have any correctness test yet that exercise real-device GPU renderings. It was very difficult before @Piinks 's Skia gold work. Now with the Skia gold, I think that's possible. Although I'm not sure what's the priority of having that done. |
@flar : BTW, I think Ian's comment might be to design a performance test to verify that you can disable the optimization after introducing a BackdropFilter, and bring that optimization back when that BackdropFilter is gone. I believe the best place to have that test is in our device lab, instead of in the engine repo because we don't have iOS devices in the engine repo. |
OK, I'm happy to address any testing of these changes under flutter/flutter#45731 |
I just don't want there to be a bug where a particular sequence of events causes us to paint the wrong thing because we're optimising it away or some such. I highly doubt that we have any tests that try to explicitly exercise this optimisation. |
After a second thought, I think there might be a correctness test with some compromises:
CC @chinmaygarde for further comments as he's currently refactoring ShellTest. |
Guidance on writing a test for this: After #14023, you should be able to create a shell by explicitly specifying I highly recommend testing this however. There are no tests introduced in this patch that will fail before this optimization but pass now (and will fail again in case of regression). Also, this is fairly intricate implementation detail that higher level tests will have a hard time authoring tests that reliably exercise the case being optimized. This optimization is also platform specific. We can still have performance tests but having another test that just reliably verifies that the optimization is in effect will surely make me feel a lot better. |
* a86ef94 Dynamically determine whether to use offscreen surface based on need (flutter/engine#13976) * 0fc7867 Roll src/third_party/dart 96e7a4ff30..73fdf19b56 (3 commits) (flutter/engine#14063) * 6c605f8 Fix fml_unittests (flutter/engine#14062)
…on need (flutter#13976)" This reverts commit a86ef94.
* Revert "Add flow test fixtures and tests (flutter#13986)" This reverts commit 620f528. * Revert "Dynamically determine whether to use offscreen surface based on need (flutter#13976)" This reverts commit a86ef94.
Keep track of layers that perform operations that read back from the surface they are rendering onto (primarily BackdropFilter) and provide that information to the platform in AcquireSurface so that the appropriate (offscreen vs screen) layer type can be chosen.
This change should have a dramatic effect on the energy usage of simple apps on iOS when no BackdropFilter is present. There are some caveats though:
There is still some testing to be done, but the basic testing of the offscreen layer only being used when there is a BackdropFilter is complete (for 1 or 2 simple examples so far) and the energy usage measured by the Xcode tools has demonstrated an improvement on, for instance, a simple LinearProgressIndicator app.
This change should provide some needed relief for flutter/flutter#31865