Search Unity

WaitForTargetFPS happening with unlimited TargetFrameRate in iOS

Discussion in 'Editor & General Support' started by roberto_sc, May 22, 2019.

  1. roberto_sc

    roberto_sc

    Joined:
    Dec 13, 2010
    Posts:
    144
    I'm seeing WaitForTargetFPS happening on iOS. Application.TargetFrameRate is set to 60 but the game is running at 30 fps. I'm using Multithreaded Rendering.

    This is what I'm getting in profiler:

    Screen Shot 2019-05-22 at 3.39.27 PM.png


    It feels like WaitForTargetFPS is waiting for the render thread, which doesn't make sense but I saw some people saying otherwise and also why would the main thread wait if the target is 60 fps and render thread is free?
     
    Last edited: May 24, 2019
  2. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    2,461
    Which exact Unity version are you using and what is QualitySettings-vSyncCount set to? Also, What generation of iPad are you profiling?
     
  3. roberto_sc

    roberto_sc

    Joined:
    Dec 13, 2010
    Posts:
    144
    Hi! I'm using Unity 2019.1.3f1, VSync count is set to zero (but I thought this wouldn't matter for iOS?) and I'm using an iPad Mini 4.
     
  4. roberto_sc

    roberto_sc

    Joined:
    Dec 13, 2010
    Posts:
    144
    @MartinTilo sorry for spamming.
    I went over this again to verify I was doing everything correct. I'm printing my Application.TargetFrameRate every 5 seconds and it is indeed 60, VSync = 0. I can achieve 60 in other parts of the game (main UI, etc) but during gameplay I get a steady 30fps with a lot of WaitForTargetFPS.
    I can't find anything related to it in Instruments.
    Is there anything else that would cause a WaitForTargetFPS?
    This is driving me nuts as I need to optimize this game asap.

    By the way, originally I was using Unity 2017.4.24f1, I was getting "Unaccounted time between..." (please check new screenshot I posted), and that was the reason that lead me to upgrade, after some googling on the issue.

    Also, how come doesn't the graph match the time line? I get around 33ms in most frames but the graph hardly reaches 30fps.
     

    Attached Files:

    Last edited: May 24, 2019
  5. roberto_sc

    roberto_sc

    Joined:
    Dec 13, 2010
    Posts:
    144
    I disabled some renderers during gameplay and it goes to 60fps - except for a few frames where they still take 33ms. My conclusion is that if a frame can't be drawn in 16.6ms WaitForTargetFPS runs to make it take 33ms.

    It would be nice to have a confirmation that it works this way. I don't remember seeing this behaviour in other projects.
     
  6. martonekler

    martonekler

    Unity Technologies

    Joined:
    Feb 5, 2015
    Posts:
    31
    Hi, could you please file bugreport with a small repro?

    Thanks,
    Marton
     
  7. roberto_sc

    roberto_sc

    Joined:
    Dec 13, 2010
    Posts:
    144
  8. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    2,461
    @roberto_sc sorry for the longer wait on my reply. So, judging by Marton's reply, it looks like this might be buggy behavior of our rendering code on iOS. BTW, which graphics backend are you using.

    Also, I've seen some users having issues with multi-threaded rendering on mobile, maybe try turning that off and see how things change. Note that that would likely mean it's a bug that should be reported and that that shouldn't be taken as general advice but something to try to isolate, where the issue lies.

    And yes, I've seen other users experience that too: that slipping by the 16.66 ms mark means they'll fall through to the 33.33 ms mark.

    Was this still on 2019.1?
    We've recently fixed how "Other" was calculated rendered to the charts, I'd have to check again where exactly that fix landed. Also, "Other" is currently hidden by default and only calculated and shown as overlay if a sample is selected (where the overlay will then highlight how much time was spend on that sample and anything below it across the different categories and all 300 frames). You could select the "PlayerLoop" sample and it should add the graph for the "Other" category. Annoyingly, gray samples such as "Unaccounted time" and "Semaphore Wait for Signal" currently gets thrown in with the "Other" category. Also, which Category gets how much time allotted to is defined by the category of whichever sample is on the top of the stack at any point in the main thread.

    to summarize, the gap between timeline view in the CPU chart is probably due to "Other" not being shown. Also, fixes for Charts have landed in 2018.3.9f1, 2019.1.0b9, 2019.2.0a11, 2019.3.0a2.

    Additionally, if the spike is to steep, the tip might get aliased away for a couple of pixels.
     
  9. roberto_sc

    roberto_sc

    Joined:
    Dec 13, 2010
    Posts:
    144
    Hello @MartinTilo.
    I'm using Metal and Multithreaded Rendering. With Multithreaded Rendering disabled I get the same behaviour, that is, WaitForTargetFPS runs to fill the 33.33ms frame.

    I'm sorry, but there's one thing I don't understand 100% in your response: you said that slipping by the 16.66 ms mark means they'll fall through to the 33.33ms mark. For me this sounds like you are saying it's the expected behaviour. Is it a bug or not?

    Thanks for the explanation on the gap between timeline view and CPU chart, that's exactly what's happening. But I must say I find this new feature... weird.
     
  10. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    2,461
    The way I understand @martonekler, this is a bug. I guess I just tried to say that I have seen people struggling with this before though.
    EDIT: this is NOT a bug. All mobile platforms can only present on a VBlank, i.e. run at an FPS equal to their their screens refresh rate or the their refresh rate divided my an integer. An update for the documentation for Application.targetFrameRate is on it's way.



    Also, just because something might be known as an issue on the forums, doesn't mean it reaches the right teams so that it is getting fixed. So if there is something off, even if people offer work-arounds, filing a bug report is the surest way to get it resolved for good. So thank you for your bug report :)


    Sorry, which feature are you referring to? The one where "Other" is only shown when a sample is selected that spends time in the "Other" category?
    If so, that is not technically a feature but more like a design flaw that needs fixing. I've created a bug report for it so that we don't forget to fix this.
     
    Last edited: Apr 30, 2020
    roberto_sc likes this.
  11. roberto_sc

    roberto_sc

    Joined:
    Dec 13, 2010
    Posts:
    144
    I see now, thanks. But what behaviour did you expect then? I'm asking because if I understand correctly in iOS we are locked to 60fps or subdivisions of 60 to match the screen refresh rate. Would you expect another method to run to complete the 33ms window instead of WaitForTargetFPS?

    Also feels like a bug because in a few cases it seemed the frame had enough space to run in a 16.66ms window but it took 33.33ms anyway (that is, WaitForTargetFPS ran for longer than 16.66ms). Unless measurements in profiler aren't 100% accurate or the budget is actually a bit less than 16.66ms.


    haha ok, I see now. Phew...:oops::D
     
  12. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    2,461
  13. roberto_sc

    roberto_sc

    Joined:
    Dec 13, 2010
    Posts:
    144
    Is this bug ever going to be looked into?

    If I understand correctly, the renderer is not rendering on every single frame that it could, thus dropping FPS average a bit. Isn't this kinda... MAJOR?
     
  14. roberto_sc

    roberto_sc

    Joined:
    Dec 13, 2010
    Posts:
    144
  15. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    2,461
    Yeah it is being looked into. There had been a bit of a misunderstanding by the QA person looking for a repro, but it is getting re-processed.
     
    roberto_sc likes this.
  16. roberto_sc

    roberto_sc

    Joined:
    Dec 13, 2010
    Posts:
    144
    Hello @MartinTilo and @martonekler

    I've got some answers from the QA team and I've decided to post them here because I'm getting a bit confused. Please bear with me and read on; this was their first answer:

    I explained them that QualitySettings.vSyncCount is set to zero, which means "Don't Sync". Then they said:

    This is just wrong.

    Can you please take a look at this with the QA/dev team, or explain to me what I can't understand? Basically, these are my premises:
    1. iOS does not ignore Don'tSync and uses "Every Second V Blank" instead;
    2. the repro project that I sent for issue id 1159050 has a slider where the tester can use to make the frame take longer and verify the framerate dropping from 60fps to 30fps when the frame is still taking less than 16.66ms. This issue has nothing to do with vSync settings as the frames drop without changing any settings, but they will only find this out if they ever run the repro project.
    Thank you.
     
  17. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    2,461
    Hi @roberto_sc,

    As I've replied to you on the bug ticket, I've reopened the ticket and tried to clear up some of the confusion on there so that this can get looked at from a cleaner slate again.
    So just to clear some of this up in here as well for others:

    Code (CSharp):
    1. When using iOS build the iOS ignores “Don’t Sync” and instead uses “Every Second V Blank”.
    This is indeed wrong information. Yes, it will ignore the vSync setting, but instead it will just flip the frame at whichever vBlank is the first one after processing of the frame and waiting for the targeted frame rate is done.

    I'm in the process of updating the documentation to reflect that.
     
    Last edited: Mar 9, 2020
    roberto_sc likes this.
  18. o1o101

    o1o101

    Joined:
    Jan 19, 2014
    Posts:
    639
    Is this public on the issue tracker? Has a fix been released?
     
  19. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    2,461
  20. libin_hope

    libin_hope

    Joined:
    May 4, 2017
    Posts:
    2
    When can I fix it? Set targetframerate = 60 to reduce FPS
     
  21. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    2,461
    I'm sorry, I don't get what you mean with either of these sentences.
    Just some thoughts though:
    1. make sure that this precise issue is what you're experiencing. There's a very high chance you are looking at something similar but quite different. Please check the Profiler documentation on custom samples for things that commonly cause confusion.
    2. If you're not sure, consider opening a new thread
    3. If it IS this issue, I don't think you can fix it until we fixed it. You can check that issue tracker link above every now and then to see if it is resolved though.
     
  22. pistoleta

    pistoleta

    Joined:
    Sep 14, 2017
    Posts:
    539
    Sorry but after so many information im not sure anymore, Is this related with the bug you linked here ?

    Im building on a MAC for iOS, using Unity 2019.4.12f and as you can see the WaitingForTargetFPS is always there using 15ms - 20.10 ms, even with the VSync set to don't sync.
    Also, the moment this frame this capture is taken the Application.targetframerate is set to 30.

    This is because during the game we switch to 30-60 depending on what the player is doing, if he moves, we set to 60, if he is still, we set to 30.



    Is this part of the bug? also, why if the VSync is off this yellow graph appears when I check the VSync checkbox in the profiler?


    Should I file a support ticket or this is the bug you are talking about ?
    Thanks in advance.
     
  23. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    2,461
    No. While some of this is certianly confusing, everything you described works exactly as documented. If you check out the documentation for Application.targetFrameRate:
    So: changing your vSync setting on iOS does nothing. You'll always have to wait for vSync on mobile and if you set the target frame rate to 30, the remaining frame time up to 33ms is gonna be eaten up by WaitForTargetFPS; a profiler sample that is categorized as vSync, i.e. yellow.

    Also, you'd likely want to look at these samples in Timeline view and check out the explanations and descriptions of these common samples in the CPU Profiler manual page for more info.
     
  24. pistoleta

    pistoleta

    Joined:
    Sep 14, 2017
    Posts:
    539
    It has NO effect at all? we set it to 30 because if we kept it to 60 all the time the device (iOS) seemed like it gained temperature and lowered fps considerably when playing for 15-20 min.... are you telling me this was not the reason? or maybe this WaitForTargetFPS it doesn't cause so much overhead as keeping it at 60fps ?

    Thanks for your help.
    pistoleta
     
  25. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    2,461
    vSync can only be set to 0,1,2 or 3. If you meant to say that you set Application.targetFrameRate to 30 or 60, then yes, that has the effect you were aiming for. Just QualitySettings.vSync is ignored on iOS, but that doesn't mean that frames on iOS can get flipped to the screen at any moment (i.e. not be vSync'ed), they still have to wait for a vBlank every 1s/screen-refresh-rate-in-hz, i.e. on all iPhones I'm aware of every 16.66ms.

    I was just trying to explain why you see vSync waiting times in the Profiler even though you turned it off in the Quality Settings.

    Setting a lower target Frame rate (or changing vSync settings on platforms where it isn't ignored, like android) when a higher framerate is not required can definitely be beneficial to avoid the device heating up an thermal throttling kicking in.
     
    pistoleta likes this.
  26. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    2,461
    And yes that
    is admittedly confusing and we'll look into bringing these explanations for the common profiler markers closer to you as a user, i.e. link back to documentation from the tooling or something to that effect to help clear up some of that confusion.
     
  27. pistoleta

    pistoleta

    Joined:
    Sep 14, 2017
    Posts:
    539
    I see, I understand now, so this is the normal behavior... vSync waiting times in iOS I mean. So I'm guessing we shouldn't be waiting for any kind of solution for this.

    Thanks a lot for your help.
     
    MartinTilo likes this.
  28. studentvz

    studentvz

    Joined:
    Dec 14, 2014
    Posts:
    149
    We have a huge problem with the iOS game when we use settings to run it on 30fps, the game is extremely jittery. But 60fps works flawlessly, something is very wrong. The game looks like it is running on 5-15fps, but it is showing stable 30fps.

    To get 30fps we use:
    targetframerate = -1 (locks game to 30fps)
    vsynccount = 2 (not relevant, same behavior with any vsync due to iOS)
    multithreaded rendering = off (because we found that it breaks vsync rendering on android)
    Result:
    On Unity 2017.4.32f1 and Unity 2017.4.40f1 jittery and unplayable.
    On Unity 2019.4.13f1 works without any issues, normal users will hardly notice a difference between 30 and 60fps.

    To get 60fps we use:

    targetframerate = 60 (only way to get 60fps, -1 and vsync 1 gives 30fps)
    vsynccount = 1 (not relevant, same behavior with any vsync due to iOS)
    multithreaded rendering = off (because we found that it breaks vsync rendering on android)
    Result:
    On Unity 2017.4.32f1 and Unity 2017.4.40f1 works as it should, fluid.
    On Unity 2019.4.13f1 drops every few seconds to 57-59fps.

    We would move our project to 2019LTS, but there is a bug with terrain tree billboard rotation so that breaks all out vegetation.

    Btw, we are not talking about very small screen tear/jitter that happens every few seconds and it is reported on numbers threads, for example, on this one: https://forum.unity.com/threads/tim...t-vsync-camerafollow-and-jitter.430339/page-7
     
    Last edited: Oct 30, 2020
  29. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    2,461
    Yes, vSyncCount is ignored on iOS, so targetFrameRate is the only way to go.

    It sounds like you might want to set
    targetFrameRate on iOS with multithreaded rendering on (unless that causes issues there too and not just on Android).
    On Android you might want to use vSyncCount instead, especially since there are android devices with "odd" non 60hz screen refresh rates and setting targetFrameRate is a recipe for a minor disaster on these, check out this thread for an example.

    Have you reported that bug? Do you have an issue tracker ID?

    Would be interesting to know what issues multithreaded rendering caused on Android though and sorry that I have no pointers for the 2017.4 issue. I feel like I'm maybe still lacking some crucial context or a profiler timeline view screenshot to grasp what is going on there...
     
  30. studentvz

    studentvz

    Joined:
    Dec 14, 2014
    Posts:
    149
    Android
    We always used just targetframerate to cap fps and made vsync optional to users, it was off by default. Our game is aimed at 60fps and interesting thing is that in 2017.4 (and 2018LTS) we have rock solid 60fps, but the same project on Unity 2019LTS can't keep 60fps, it bounces back to 58-59fps every few seconds and gets back to 60fps. We "fixed" it by setting targetframerate to 61fps, and that made it a solid 60fps. Something happened with targetframerate in Unity 2019. Check this post (with Android in mind), and link to another post in that post: https://forum.unity.com/threads/uni...-not-touching-the-screen.511902/#post-6366366.

    Multithreaded rendering on Android makes the game stuttery/jittery, especially on 30fps with vsync on, it looks almost identical to the iOS 30fps jittery problem on 2017.4.

    Once we solve issues with iOS which is a top priority currently I can get back to testing on Android and test fps capping with vsync and other things, for example, fps performance, stability, and smoothness degradation from 2017.4.7 -> 2018LTS -> 2019LTS but that is a topic for another thread (and there are already threads about this).

    iOS
    I can confirm that multithreaded rendering on 2019LTS does not produce stuttering.
    On 2017LTS it looks as it makes things worse, I even suspected that maybe somehow multithreaded rendering was always on and it was breaking smoothness on 30fps, as it does on Android.
    In the last few days, we made a few dozens builds with various settings in 2017.4 and didn't find any rational reason why this happens. I can again make some tests and provide you a profiler screenshot, maybe a whole project over bug report, but even if we determinate a bug what will happen? Unity 2017 updates are over as it looks.

    With 2017.4LTS we get a rock-solid 60fps on our targeted device but if users have some older iPads with high resolution and they need to use 30fps, they will get a jittery unplayable game.
    With 2019.4LTS we get a bit worse performance - unstable 60fps, broken tree billboards, but the 30fps issue and some iOS bugs are fixed.

    I will test 2018LTS today to maybe mitigate these issues, but I'm afraid that this version could still have iOS bugs that were fixed in 2019LTS.

    Terrain tree billboard bug on 2019LTS is reported: Case 1287879
     
  31. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    2,461
    Yeah but vSync isn't optional on mobile, it is mandated by the OS. The urban legend that vSync is bad for performance, smoothness or input is just a myth based on bad rendering pipeline work in engines, not an actual thing. And on mobile, as said, you literally can't escape vSync and by setting targetFrameRate you're probably making it worse as you let the CPU hold up the frame time via the imprecise Thread.Sleep instead of letting the GPU take point on this.

    On iOS you obviously have to set the targetFrameRate as vSync setting is ignored but only 30 and 60.

    No idea why this should work but really, try vSyncCount = 1 or 2 and leave targetFrameRate at -1 on Android. And don't rely on an FPS display that uses Time.deltaTime on versions pre 2020.2 (i.e. without this fix) for your performance measurements.
     
  32. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    2,461
    Then again, judging by my other colleagues words over here, maybe the magic sauce needed here is optimized frame pacing.
     
  33. studentvz

    studentvz

    Joined:
    Dec 14, 2014
    Posts:
    149
  34. MartinTilo

    MartinTilo

    Unity Technologies

    Joined:
    Aug 16, 2017
    Posts:
    2,461
    Yeah looks like on mobile, Application.targetFrameRate might be the way to go. FYI, this thread sparked a cross team collaboration to build out a documentation page with recommendations for ideal settings as a good basis for getting a smooth frame rate.

    Part of that is recommendations to review your Time settings, specifically the FixedUpdate intervals (recommended to set at 16ms so it's once per frame on 60fps and twice on 30fps, instead of it being something uneven and flip-floping frame over frame) and the max time step at 0.1s as at that point you have a different problem already and can otherwise fall into the physics spiral of death.