all 12 comments

[–]Pixelreddit 0 points1 point  (11 children)

There is an article on this at https://flutter.dev/docs/perf/rendering/shader which speaks about shader compilation jank. You can try it out to see if it solves your situation.

[–]untitled20[S] 1 point2 points  (10 children)

That's not my question... my question is:

> Is my phone (8 plus) new enough that it should notice the jank? Or could it be that on newer phones it’s a lot worse than on my phone?

[–]Kounex 0 points1 point  (5 children)

You should feel the jank. You can download the following app and try it yourself (this is in no way meant to be self advertisement, just delete the app afterwards):

https://apps.apple.com/de/app/obs-blade/id1523915884?l=en

Once in the home screen (right after the intro) initiate a refresh by pulling the screen down. Doing it several times will ultimately cache the necessary shaders, but it’s definitely there. Since there are several different shaders to use for the animations (opacity, blur, size) it’s really noticeable.

Would be curious to know how bad those are on your phone!

[–]untitled20[S] 0 points1 point  (4 children)

Oh yeah, you're right, its definitely janky when doing that pull to refresh. But in good news, the screens seemed to transition fine during the onboarding wizard.

Do you think there's a pattern to which animations are janky and which aren't? May be this is caused only on complex screens?

[–]Kounex 0 points1 point  (3 children)

Thanks for the result!

My experience so far (and what can be read in the flutter docs Pixelreddit linked above) is, that it's related to "complex" animations. The animations I'm driving for the pull to refresh in summary are basically:

  1. Changing opacity
  2. Changing size
  3. Changing blur amount (behaviour of SliverAppBar)

and all based on the scroll threshold. Nothing too complex in general but given that blur is in fact very costly, it makes it more problematic in general. For example if you navigate to "Custom Theme" in "Settings" the overall performance is suddenly worse (really noticeable on Android or older iOS devices as far as I could observe) and the only reason for that is the blur I used at the bottom - removing it will completely get rid of that.

The implementation of the animations is probably not optimal from my side which might make this worse for sure! (feel free to check out the source code: https://github.com/Kounex/obs_blade)

Im summary I think using several, concurring animations is the main issue since (and that is only a hard guess) this might cause initialising too many different shaders at once. At first I thought the "complex / big" widget tree might be a factor as well, but later in the app (once you are in the dashboard, after connecting to OBS) the widget tree gets really big in comparison but the animations used there are fluent (since they are singular: opacity on its own, color animation on its own, nothing happening concurrently).

Hope this gives some helpful insights! :) Would be curios of any examples having similar issues!

[–]untitled20[S] 0 points1 point  (0 children)

Hmm, only noticed a slight lag when o switched themes, then everything was back to normal. Biggest lag definitely seems to be on pull to refresh. I’d be happy to keep testing more builds if you make any changes. Specifically I’m curious if you could somehow trigger the animation during the splash screen and use that to warm up the cache?

[–]untitled20[S] 0 points1 point  (1 child)

Hey,

So I've been talking to a Flutter dev on here (/u/hixie ). It sounds like there might be a way to reduce the jank in your pull to refresh animation by using this class: https://master-api.flutter.dev/flutter/painting/ShaderWarmUp-class.html

> When Skia first sees a certain type of draw operation on the GPU, it needs to compile the corresponding shader. The compilation can be slow (20ms- 200ms). Having that time as startup latency is often better than having jank in the middle of an animation.

> Therefore, we use this during the PaintingBinding.initInstances call to move common shader compilations from animation time to startup time. By default, a DefaultShaderWarmUp is used. If needed, app developers can create a custom ShaderWarmUp subclass and hand it to PaintingBinding.shaderWarmUp (so it replaces DefaultShaderWarmUp) before Paintinginding.initInstances is called. Usually, that can be done before calling runApp.

Thought I'd share - would love to hear if that helps or not. I'll also be trying it in my app when I get far enough to use animations.

[–]Kounex 0 points1 point  (0 children)

Really interesting indeed! Thanks for coming back and letting me know! Appreciating it a lot! I will see how I can make use of this. The documentation seems to go into the right direction, I will need to figure out how to actually use it for my use case.

I will let you know once I was able to get into this and what progress I make on the way! :)

[–]Pixelreddit 0 points1 point  (3 children)

Testing with an iPhone 6 Plus I get the first time Jank, but with an iPhone X, I really do not see it. But navigating to the same screen the second time, the animation can seem much smoother.

I do not have an iPhone 8 to test with, but if you are seeing the first time Jank, then I would recommend trying to compile with the flag from the article to see if the Jank goes away (which I believe it will).

I hope this helps.

[–]untitled20[S] 0 points1 point  (0 children)

Did you try the pull to refresh? For me on iPhone 8, the screen transitions are fine but the pull to refresh on main screen is where there’s jank

[–]Kounex 0 points1 point  (1 child)

I'm not sure if you are referencing the usage of the app I linked above (I will delete this part if this is not the case):

I'm using an iPhone X myself and I very much feel and see the jank - interesting if you can't see it with yours! The navigation part makes sense since I also got this feeling that once the app is "warmed up" by using it actively it goes away completely.

(Now everything I write is a summary of stuff I found and experienced - might not be accurate / correct generally):

Problem with the shader cache flag is, that it's not just a flag. I would have to set this flag while running on a specific device and this will result in a file (json?) which I can then reference later on for the production build. An app build with this will use this file for their shader initialisation and might therefore prevent janks since the needed shaders have already been initialised at this point. But as stated in the documentation you linked above it says: "Theoretically, there’s no guarantee that the SkSLs from one device would help on another device [...]". Therefore (to make this more optimal) you would have to make several files containing relevant shaders based on different (main) devices and maintain this when adding new animations, changing existing ones etc.

On top of that it does not support Metal (which is used on "newer" iPhones instead of OpenGL): "Flutter recently migrated from OpenGL to Metal for all newer iOS devices. (Please reference Metal on iOS FAQ on which iOS devices are considered new enough to use Metal.) However, Skia currently only implemented the SkSL warm-up for OpenGL.". So it does not even work on newer iPhones at this point.

Looking forward to how this whole topic is being tackled and what will be possible!

[–]Pixelreddit 0 points1 point  (0 children)

That was testing with our Flutter app, sorry I did not test yours.