Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[integration_test] Support collecting of SkSL #85118

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

Closed
wants to merge 2 commits into from

Conversation

jiahaog
Copy link
Member

@jiahaog jiahaog commented Jun 23, 2021

Passing --write-sksl-on-exit=sksl.json to flutter test when running in Integration Test mode will collect shaders to the specified file.

  • Slightly pushes back when IntegrationTestDevice.observatoryUrl completes, so that we avoid duplication of state and keep one instance variable that tracks both the observatory and the vm service
  • Modified FakeVmService to copy the requests list since it will be mutated and is unexpected when reusing the requests list over multiple fakes

TODO:

  • Verify that the collected shaders actually work
  • Multiple tests will generate multiple shader files, probably want to only run this when one test file is specified

Pre-launch Checklist

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • I read the Tree Hygiene wiki page, which explains my responsibilities.
  • I read and followed the Flutter Style Guide, including Features we expect every widget to implement.
  • I signed the CLA.
  • I listed at least one issue that this PR fixes in the description above.
  • I updated/added relevant documentation (doc comments with ///).
  • I added new tests to check the change I am making or feature I am adding, or Hixie said the PR is test-exempt.
  • All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel on Discord.

@flutter-dashboard flutter-dashboard bot added the tool Affects the "flutter" command-line tool. See also t: labels. label Jun 23, 2021
@google-cla google-cla bot added the cla: yes label Jun 23, 2021
@jiahaog
Copy link
Member Author

jiahaog commented Jun 24, 2021

@dnfield I managed to wire it up with Integration Tests here. But when I tried reusing the collected SkSL, (following the repro from #76180), it didn't seem to help eliminate jank, while the manually collected ones through flutter run --cache-sksl did for me locally. Do you know if it's possible that with the IntegrationTestWidgetsFlutterBinding bindings, the collected SkSL is somehow different from the ones expected in a normal app?

@dnfield
Copy link
Contributor

dnfield commented Jun 24, 2021

If you compare the JSON output are they different?

@jiahaog
Copy link
Member Author

jiahaog commented Jun 25, 2021

Yes, they are different (uploaded here). I've checked the usual things - running in profile mode on the same iOS physical device, software rendering is disabled, not sure if you have any ideas.

@dnfield
Copy link
Contributor

dnfield commented Jun 25, 2021

Could it be the extra repaint boundary we added?

@hazzo
Copy link

hazzo commented Aug 18, 2021

I found this draft PR looking for something similar. Sorry to to bother here, but I indeed stumbled with disappointment that compiled shaders extracted from integration test don't reduce jank at all. Why is this?

@jiahaog
Copy link
Member Author

jiahaog commented Aug 18, 2021

Sorry, I haven't had time to follow up and investigate further. As Dan mentioned, it could be due to the extra repaint boundary that we use to wrap all widgets, or some subtle difference in how the IntegrationTestWidgetsFlutterBinding differs from the default WidgetsFlutterBinding.

@hazzo
Copy link

hazzo commented Aug 18, 2021

This is a huge bummer. In the documentation https://flutter.dev/docs/perf/rendering/shader it talks how integration tests could make the task of compiling shader cache easier and it does not specifies that the new integration_test will run useless the exported shaders. I have a bunch of tests written the new way that you are telling me that I can't use to compile shaders?

The jank issues have been (since I started with flutter) the worst part of all the delightful experience flutter is. I accepted and realised that compiling shaders is a temporary solution that solves a problem with good results. But been not able to make this automatically brings us way back again to not solving the jank issues at all. Manual shader compilation by playing with the app is not acceptable for large scale applications.

Sorry to repeat this but is a huge disappointment.

@dnfield
Copy link
Contributor

dnfield commented Aug 20, 2021

I strongly suspect it's this code here that's causing trouble:

if (_pointers.isNotEmpty) {
final double radius = configuration.size.shortestSide * 0.05;
final Path path = Path()
..addOval(Rect.fromCircle(center: Offset.zero, radius: radius))
..moveTo(0.0, -radius * 2.0)
..lineTo(0.0, radius * 2.0)
..moveTo(-radius * 2.0, 0.0)
..lineTo(radius * 2.0, 0.0);
final Canvas canvas = context.canvas;
final Paint paint = Paint()
..strokeWidth = radius / 10.0
..style = PaintingStyle.stroke;
bool dirty = false;
for (final int pointer in _pointers.keys) {
final _LiveTestPointerRecord record = _pointers[pointer]!;
paint.color = record.color.withOpacity(record.decay < 0 ? (record.decay / (_kPointerDecay - 1)) : 1.0);
canvas.drawPath(path.shift(record.position), paint);
if (record.decay < 0)
dirty = true;
record.decay += 1;
}
_pointers
.keys
.where((int pointer) => _pointers[pointer]!.decay == 0)
.toList()
.forEach(_pointers.remove);
if (dirty && onNeedPaint != null)
scheduleMicrotask(onNeedPaint);
}
_label?.paint(context.canvas, offset - const Offset(0.0, 10.0));

@jiahaog - are you set up to easily verify if deleting that code produces the expected shaders or not?

@jiahaog
Copy link
Member Author

jiahaog commented Aug 21, 2021

Thanks Dan for the pointer, I'll try that out and update here

@hazzo
Copy link

hazzo commented Aug 24, 2021

I made a test my self commenting the code you @dnfield suggested and it does not seem to fix the issue of janks on first run. I commented the lines in the file in the dart package and then run the integration test. I don't know if that is enough or I have to do an extra step.

@hazzo
Copy link

hazzo commented Aug 24, 2021

Oh I have to say that the compiled shaders JSON file size was reduced on this run with the commented lines. So it seems that something is doing but not enough.

@dnfield
Copy link
Contributor

dnfield commented Aug 24, 2021

I'm suspicious of that code because it changes what gets drawn and thus might change shaders. We have to see if there are other places too.

@hazzo
Copy link

hazzo commented Aug 24, 2021

It definitively change shaders because size was reduced. My question is, do you consider that this issue will get fixed and integration_test package will be a valid way to generate shaders? Or is safer if I re write them the "old way"? I want to know your opinion on this because now I have some feature tests but if in a couple of months the app grows it would be kind of annoying to re write them the old way.

Thanks!

@dnfield
Copy link
Contributor

dnfield commented Aug 24, 2021

This is a prolem we want to fix, but I don't have an estimate on when it will be fixed right now.

What do you mean the size is reduced? I thought integration_test was using the native device resolution.

@hazzo
Copy link

hazzo commented Aug 24, 2021

Okey so I will continue doing tests this way and making cache shaders by playing around with the app.

By reduced size I mean that the json file first was around 217kb and after commenting the code you suggested the json was 191kb.

@dnfield
Copy link
Contributor

dnfield commented Aug 24, 2021

Ah! yes, a change in size would be expected since you're not compiling the same shaders anymore.

It would be helpful to compare the files against a regular flutter run --profile, or a flutter_driver based test.

@dnfield
Copy link
Contributor

dnfield commented Aug 24, 2021

Also, I'm assuming you're running in profile mode on a real device.

@hazzo
Copy link

hazzo commented Aug 25, 2021

Yes, real device and profile.

flutter drive --profile --cache-sksl --write-sksl-on-exit flutter_01.sksl.json --driver=test/integration_test_driver.dart --target=test/${TARGET}

I'll try to get some time to compare the .json files.

@hazzo
Copy link

hazzo commented Aug 25, 2021

I have one doubt that got me thinking. Running multiple group tests in a single file, initialising apps main method in each group could lead to wrong shaders?

For example:

void main() {
  IntegrationTestWidgetsFlutterBinding.ensureInitialized();

  group('smoke test', () {
    testWidgets('test 1', (WidgetTester tester) async {
        app.main();
        await tester.pumpAndSettle();
        await testOne(tester);
    });

    testWidgets('test 2', (WidgetTester tester) async {
        app.main();
        await tester.pumpAndSettle();
        await testTwo(tester);
    });
  });

  group('smoke test logged', () {
    testWidgets('test 3', (WidgetTester tester) async {
        app.main();
        await tester.pumpAndSettle();
        await testThree(tester);
    });
  });
}

@dnfield
Copy link
Contributor

dnfield commented Aug 25, 2021

I don't think so, but it would be worth isolating

@jiahaog
Copy link
Member Author

jiahaog commented Aug 31, 2021

The changes mentioned in #85118 (comment) did not help. I was able to get the collected shaders with this to work with a few modifications to the integration test:

Approach 1 - setting the frame policy, using timeouts

https://github.com/jiahaog/hello_flutter_integration_test/blob/2a423a4ea157cec90d395ab27ef7e0663977d283/integration_test/collect_sksl_test.dart#L9-L34

Approach 2 - Large time dilation value

https://github.com/jiahaog/hello_flutter_integration_test/blob/20d77e8842aa055345ef3a3151b8dda9ecb64469/integration_test/collect_sksl_test.dart#L8-L26

The value of timeDilation required for pumpAndSettle is fairly large. I suspect that using pumpAndSettle is potentially expensive, which relates to #84994 where frames are missed, preventing the shaders from being cached properly, so we need to set the time dilation to a large value.


I'm less favourable to the first approach since that requires the use of timeouts, and changing the frame policy may not be compatible with existing tests, which does not make them portable for both regular testing and collecting of SkSL.

@dnfield any thoughts about the above? For approach 2 we could potentially send a signal from the Tool to the test to increase the time dilation, though it may not be easy to choose a good value. Or is there a way to disable frame skipping entirely (as mentioned in #84994)? Then existing tests can be reused without code changes.

Workspace for reference: https://github.com/jiahaog/hello_flutter_integration_test/tree/cache-sksl

@hazzo
Copy link

hazzo commented Aug 31, 2021

The changes mentioned in #85118 (comment) did not help. I was able to get the collected shaders with this to work with a few modifications to the integration test:

Approach 1 - setting the frame policy, using timeouts

https://github.com/jiahaog/hello_flutter_integration_test/blob/2a423a4ea157cec90d395ab27ef7e0663977d283/integration_test/collect_sksl_test.dart#L9-L34

Approach 2 - Large time dilation value

https://github.com/jiahaog/hello_flutter_integration_test/blob/20d77e8842aa055345ef3a3151b8dda9ecb64469/integration_test/collect_sksl_test.dart#L8-L26

The value of timeDilation required for pumpAndSettle is fairly large. I suspect that using pumpAndSettle is potentially expensive, which relates to #84994 where frames are missed, preventing the shaders from being cached properly, so we need to set the time dilation to a large value.


I'm less favourable to the first approach since that requires the use of timeouts, and changing the frame policy may not be compatible with existing tests, which does not make them portable for both regular testing and collecting of SkSL.

@dnfield any thoughts about the above? For approach 2 we could potentially send a signal from the Tool to the test to increase the time dilation, though it may not be easy to choose a good value. Then existing tests can be reused without code changes.

Workspace for reference: https://github.com/jiahaog/hello_flutter_integration_test/tree/cache-sksl

This means that tests will be longer with a time dilation so big? In my test I had to use several pumpAndSettle consecutively as it was the only way to advance some frames. My whole test skips frames abruptly but I did not think that this would affect the generated shaders.

The time delation for some complex animations may be needed to be longer?

@jiahaog
Copy link
Member Author

jiahaog commented Aug 31, 2021

Yes, you may be able to find some success by playing around with the time dilation value.

@dnfield
Copy link
Contributor

dnfield commented Aug 31, 2021

I think this makes sense - if your test skips frames (perhaps because of shader compilation), it will likely not have shaders.

I agree that time dilation is probably the way to go. I think as long as it's set low enough it should just work right? It sounds like what we basically want is something where the framework gets to render every possible frame of every animation. Time dilation is more or less a timeout in this sense, since we're saying we'll slow things down and that should be enough for the rasterizer to finish its work on every frame. That should work in most cases, but it would be even better if we just had some kind of new frame policy like neverSkip or something.

@jiahaog
Copy link
Member Author

jiahaog commented Aug 31, 2021

I'm not sure if frame skipping happens within the framework or engine, would you have a pointer to the code that controls that?

@dnfield
Copy link
Contributor

dnfield commented Sep 1, 2021

You'd have to do some tracing through the scheduler binding - I think if you look at the way the time dilation logic is handled, it may be possible to instead just adjust it so that it appears that we've always passed a single frame's worth of time (e.g. 16ms).

@jiahaog
Copy link
Member Author

jiahaog commented Sep 1, 2021

Thanks, I'll try that out 🙂

@Hixie
Copy link
Contributor

Hixie commented Nov 30, 2021

flutter test runs the tests in an 800x600 window with dpr=3x, which is extremely different from most phones. Could that be an issue?

(Should we close this PR? It hasn't been touched in a while.)

@dnfield
Copy link
Contributor

dnfield commented Dec 1, 2021

integration_test overrides those settings to match the size/dpr of the host device.

I think we should close this. The guidance around using SkSL is about to change anyway.

@dnfield dnfield closed this Dec 1, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
tool Affects the "flutter" command-line tool. See also t: labels.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants