Bug 173434 - Support for 120Hz requestAnimationFrame
Summary: Support for 120Hz requestAnimationFrame
Status: NEW
Alias: None
Product: WebKit
Classification: Unclassified
Component: Canvas (show other bugs)
Version: WebKit Nightly Build
Hardware: All All
: P2 Enhancement
Assignee: Nobody
URL: http://www.testufo.com
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2017-06-15 14:16 PDT by mdrejhon
Modified: 2024-04-12 05:57 PDT (History)
20 users (show)

See Also:


Attachments
Accidentally misleading tooltip by Safari Browser on MacOS (100.25 KB, image/jpeg)
2023-12-26 14:08 PST, mdrejhon
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description mdrejhon 2017-06-15 14:16:41 PDT
The 120Hz iPad only supports 60fps/60Hz at http://www.testufo.com and http://www.vsynctester.com

Precedent:
Currently, FireFox, Chrome, and even Edge/IE all supports animation rates greater than 60Hz since 2013, and both Chrome/FireFox browsers work at 240fps on the new true-240Hz gaming monitors (e.g. Acer Predator XB252Q, Acer Predator XB272Q, ASUS ROG PG258Q, AOC AGON AG251FZ, BenQ Zowie XL2540, BenQ Zowie XL2546).  Currently, Chrome/FireFox has no cap on the maximum possible refresh rate, and a test on a laboratory 480Hz display resulted in 480fps, and enough performance exists to run at >2000 callbacks to requestAnimationFrame in full-screen simple animations on top-end desktop GPUs (chrome --disable-gpu-vsync command line option)

HTML 5.2 standard:
A recent change was made to HTML 5.2 (DRAFT 8) -- https://github.com/w3c/html/issues/785 -- whereupon there should not be a refresh rate limitation on requestAnimationFrame() during unconstrained situations.  

Minimum Possible Compliance situation:
This specifically declares a lowest common denominator: When the iPad is in a unconstrained situation (no performance limit, temperatures are cool, power plugged into iPad charger, and not in a user-activated power-saver mode), the iPad needs to follow HTML 5.2 DRAFT 8 where animations "MUST NOT" (RFC2119) have a refresh-rate cap during system-unconstrained situations.

Preferred compliance situation:
The ideal situation is that 120fps will also run on battery power whenever CPU/GPU overheads are small enough, to permit people to view motion tests to realize the benefits of 60Hz vs 120Hz.  Such as http://www.testufo.com and the multiple selectable motion tests (selectable at upper right corner).   There are good reasons to throttle requestAnimationFrame (background, offscreen, battery low, high resource utilization, etc) but by default, low-overhead animations (e.g. requestAnimationFrame executing in less than 1ms) should be permitted to run on battery power at full sync to refresh rate.
Comment 1 mdrejhon 2017-06-15 14:23:28 PDT
Available rAF() Synchronization/Performance Test Suites:
www.vsynctester.com
www.testufo.com/#test=animation-time-graph
www.testufo.com/#test=animation-time-graph&measure=rendering

Related Articles:
www.blurbusters.com/blur-busters-working-on-changes-to-html-5-2/

(Note: I am an Invited Expert in W3C Web Platform Working Group)
Comment 2 mdrejhon 2017-07-12 16:22:07 PDT
A comment was made by someone that 120fps and higher would ideally be done via a user request (like .requestFullScreen() API).   

If this is absolutely necessary to ask the user, discoverability of refresh rate should be provided (e.g. returns "120"), along with discoverability of a throttle (e.g. returns "60").   

Consensus in talks indicates improved discoverability is essential.  It is necessary to inform the JavaScript applications what the refresh rate is, and what the current throttle is (awareness of running animations at lower than refresh rate).  Currently, this is impossible -- several websites such as http://www.testufo.com relies on heuristics to discover the current refresh rate -- but this can be completely impossible in the very few browsers (such as iPad 120Hz Safari) throttled/locked to the assumption of 60 animation callbacks per second regardless of refresh rate.

This discoverability of refresh rate & animation throttles would be put in as part of Phase 1 of the pending W3C HTML work, issue #375

VSYNC & Refresh Rate extensions to HTML standard:
PHASE 1 -- Discoverability -- https://github.com/w3c/html/issues/375#issuecomment-306591154
PHASE 2 -- New API changes -- https://github.com/w3c/html/issues/375#issuecomment-306603305
Comment 3 mdrejhon 2020-01-05 02:48:01 PST
This problem will become bigger once the rumored 120 Hz iPhone comes out in 2020.  There needs to be a solution to this.

Google "test my refresh rate" and TestUFO is #1 in all search engines.
Comment 4 Simon Fraser (smfr) 2020-01-06 10:49:51 PST
We follow the WHATWG HTML spec, not the W3C one.
Comment 5 mdrejhon 2020-01-06 16:10:20 PST
At the minimum, a nominal support for 120Hz requestAnimationFrame() only.

FireFox and Opera are compliant despite them using WHATWG.  It's not mutually exclusive...  There is nothing in WHATWG specifying that it must be limited to 60Hz.

Many vendors including NVIDIA quotes TestUFO as their test of choice.  For example, NVIDIA announced a partnership with BlurBusters in a TestUFO demo that is compatible with their 360 Hz gaming monitor -- https://www.nvidia.com/en-us/geforce/news/nvidia-geforce-360hz-esports-gaming-monitor/

There is a dramatic spike of mobile visitors to TestUFO, now being visited by million visits per month.   

Other websites, have started to assume that requestAnimationFrame matches refresh rate, and even Microsoft Edge (the Chromium version) now is compliant.   

Apple Safari is now the lone browser that cannot do 120Hz requestAnimationFrame()
Comment 6 mdrejhon 2020-01-14 11:30:40 PST
New article:
Competing mobile phone manufacturers are using TestUFO to show off 120 Hz and 144 Hz:
https://www.lowyat.net/2020/203823/xiaomi-releases-demo-video-of-redmi-k30-5g-display-running-with-144hz-refresh-rate/

You see the YouTube video.  Apparently, they modified generic Webkit to be 144fps compatible, so ignore the "UNSUPPORTED" message (it will be remedied in a future version of TestUFO update)

It would be in Apple's business interests to make sure that 120 Hz iPhone (when it comes out later this year), supports 120fps requestAnimationFrame() minimally.  It is not mutually exclusive with complying with the WHATWG specification.

Power consumption is also indeed a legitimate worry but this can be solved by giving the user the choice of Performance versus Efficiency.

Google "Blur Busters" in the news lately.  As an entity in the Refresh Rate Race to future Retina Refresh Rates, we're square and center in many of these standardization initiatives.

Minimal fps=Hz sync support is easy to do, and (now with Microsoft falling in line) is quite defacto standardized in all web browsers by all vendors on all desktops, tablets, and mobiles -- with the sole exception of Apple.  We should probably join WHATWG to send this memo.

I have lots of Apple devices (own 4 iPads) and being in the Apple ecosysystem too, it is a bit concerning that Apple has been a laggard in the refresh rate race.  The spatial retina resolution cow was milked, and now the pressure is on commoditizing retina refresh rates, so it is no longer a fad.   4K was insanely expensive 20 years ago, and now 4K is a Walmart sale.  High-Hz will be pervasive as it is another area of progress that has freed up thanks to technology.   Browsers need to keep up, and Apple should too.  Politics on power vs performance can be solved by a simple setting.
Comment 7 mdrejhon 2020-01-14 11:38:03 PST
I should also add, I understand requestAnimationFrame was never originally intended to be the primary VSYNC method.

However, ALL methods that syncs to VSYNC (whether be scrolling, or WebGL, or requestAnimationFrame), needs to be high-Hz compatible -- 

The existing politics on excluding requestAnimationFrame needs to be re-evaluated on the mainstream basis -- 

The widespread logical mutual agreement to "everything we did in the past that syncs to VSYNC should best-effort sync to Hz" -- rather than cherrypicking which APIs are allowed to sync to Hz, when in the past they used to (at 60Hz). 

It's a new refresh rate race that needs to be evaluated on its genuine human-benefits merits, including making sure past APIs are compatible with this new reality.  Much like how browser APIs had to be changed to account for retina resolution screens in a broad-spectrum manner without cherrypicking.   The same is true for retina refresh rates.
Comment 8 mdrejhon 2020-01-14 11:38:20 PST
I should also add, I understand requestAnimationFrame was never originally intended to be the primary VSYNC method.

However, ALL methods that syncs to VSYNC (whether be scrolling, or WebGL, or requestAnimationFrame), needs to be high-Hz compatible -- 

The existing politics on excluding requestAnimationFrame needs to be re-evaluated on the mainstream basis -- 

The widespread logical mutual agreement to "everything we did in the past that syncs to VSYNC should best-effort sync to Hz" -- rather than cherrypicking which APIs are allowed to sync to Hz, when in the past they used to (at 60Hz). 

It's a new refresh rate race that needs to be evaluated on its genuine human-benefits merits, including making sure past APIs are compatible with this new reality.  Much like how browser APIs had to be changed to account for retina resolution screens in a broad-spectrum manner without cherrypicking.   The same is true for retina refresh rates.
Comment 9 mdrejhon 2020-01-16 13:29:10 PST
It appears that Generic WebKit now supports 144 Hz in the new smartphone:

https://www.blurbusters.com/xiaomi-uses-testufo-to-demo-144-hz-redmi-5g-
smartphone-apple-does-not-support-120-hz-testufo/

I have published the above article to the media side of Blur Busters (Blur Busters also has a laboratory side too).

Currently, Blur Busters has media plans to more loudly call-out the 120 Hz browser limitation once Apple launches the upcoming 120 Hz smartphone.

Will attempt to join the WHATWG prior to them, time-permitting, to try to faciliate an accelerated resolution -- but it would be nice to see Apple make some headway towards falling in line with defacto industry standard.
Comment 10 mdrejhon 2020-01-16 15:28:05 PST
I have formally joined WHATWG and have submitted an issue relating to this;

https://github.com/whatwg/meta/issues/158
Comment 11 ヨハネ 2020-07-03 06:25:46 PDT
I want you to support 120hz of iPad.
Comment 12 jdspugh 2021-02-10 10:41:40 PST
As a game developer, lover of performance, and user of Apple products, I think the 120Hz capable iPads should allow 120Hz games within the browser. The users deserve the best experience possible, especially if the device is plugged into power. Otherwise why not limit the whole of the app store's apps to 60Hz also? It doesn't make sense.
Comment 13 Darcey 2021-03-31 10:57:05 PDT
There needs to be support for different refresh rates as WebGL scenes are all over the place if the user/viewer is not @ 60hz refresh rate.

requestAnimationFrame(fn,refreshRate)

I tried my website on latest version of chrome dated 31/03/21 today with my monitor set to 120hz, it virtually maxed out all my cores on my i9 9900k and didn't touch my GPU (RTX 3080), not to mention it struggled to get above 22fps, where as if I had my refresh rate set to 60hz the WebGL scene would be locked at 60fps not a problem. Yes checked chrome was using hardware acceleration, tried it on and off, same result.

Firefox on the other hand, didn't touch the CPU but used the GPU (which is correct) and nearly managed to get to 120fps, bounced around at 100 to 115.

So then I changed to 75hz refresh rate, chrome one again started to use my GPU instead of my CPU and managed to get 75fps, still overshooting 60fps and firefox was the same.

This is an old issue in the gaming industry, when one processor / gpu is faster than another measures were needed to maintain consistent speeds of animation between the different hardware. It's only going to get more and more common with new monitors to be running at varying different refresh frequencies (75, 90, 100, 110, 120, 240 etc), there even one that run at 300hz or 400hz or something, completely stupid imo, but it exists.
Comment 14 Lucas Garron 2021-08-17 17:20:03 PDT
I would also love to see 120Hz support in Safari on iPad Pro (and any potential iPhones with ProMotion).

If battery is a significant concern, could I suggest that web apps at least have access to 120Hz `requestAnimationFrame` for WebGL animations when they are added to the home screen?

Let me explain my motivation: I'm collaborating on a library to animate Rubik's Cubes and similar puzzles.
https://js.cubing.net/cubing/
https://github.com/cubing/cubing.js

For some applications, it's valuable to animate solves in real time.

- Solvers regularly perform more than 10 moves per second, with someone recently reaching 14 moves per second in a real-world solve: https://www.youtube.com/watch?v=ebPh2i53TBk
- People can also solve virtual cubes using a keyboard at comparable speeds, where they would benefit from high frame rates similar to gamers. 
- There is a physical robot that can even reach 50 moves per second: https://www.youtube.com/watch?v=nt00QzKuNVY

Sticking with the real solve example, with 14 moves per second at 60Hz: that's only ≈4 frames to animate a move, with faster moves potentially having only 2 or 3 frames. At this rate, moves would almost jump from start to finish, whereas 120Hz would offer a few frames of interpolation for the eye to follow. Empirically, this kind of difference can really make the animation much easier for cubers to follow along with.

Also for context: I just measured our drawing code, and we're able to draw fairly complex puzzles at about 6ms per frame: https://experiments.cubing.net/cubing.js/stress-tests/40x40x40.html
For some situations (e.g. smaller canvas, simpler puzzle, simpler rotations), I've been able to observe close to 1ms per frame.
That shows that there is definitely room to support 120Hz while keeping web apps responsive.

I would really prefer not to look into other devices or workarounds. The iPad Pro is really convenient and powerful for running web apps, and I would love to be able to use it for 120Hz WebGL animations. 😃
Comment 15 jdspugh 2021-08-18 23:42:47 PDT
The refreshRate is redundant for the requestAnimationFrame function. You only need requestAnimationFrame(fn). Your code will be like this:

const FPS = 240
const MILLISECONDS_PER_FRAME = 1000 / FPS
let tStart = Date.now()
let tickTarget, tick = 0
function fn() {
  tickTarget = (Date.now() - tStart) / MILLISECONDS_PER_FRAME
  while (tick < tickTarget) {
    // perform MILLISECONDS_PER_FRAME worth of game animation calculations
  }
  // render your game
  requestAnimationFrame(fn)
}
requestAnimationFrame(fn)

Now your game will run with maximum smoothness at any refresh rate up to 240fps. It's really just the basics of game programming ;)
Comment 16 Darcey 2021-08-19 04:27:38 PDT
@jdspugh I'm not a games programmer, but ah yes, that time old classic of fps not syncing with computer cpu/gpu and capabilities and frame rates. Aka Delta Time. Different languages different ways, same thing.

I should have looked into the functionality of requestAnimationFrame more...

But cheers for the code and the memory recollection of that solution.
Comment 17 mksl 2021-11-07 14:34:41 PST
@jdspugh are you sure about that? The documentation at: 
https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame 

would suggest refreshrate *does* matter to using requestAnimationFrame specifically:

>The number of callbacks is usually 60 times per second, but will generally match >the display refresh rate in most web browsers as per W3C recommendation. 

note the usage of "usually", "generally", "most".
Comment 18 jdspugh 2021-11-07 16:08:46 PST
@mksl My code snippet will run a game's simulation logic at the specified rate e.g. 240 fps. The render rate will depend on the device: 30/60/120 fps etc. So the game will function the same i.e. not speed up or slow down on devices with different refresh rates but the number of simulation updates the user sees will depend on the device's refresh rate.

Even though the above code overcomes the problem of simulating games on devices with different refresh rates, I still believe there must be a way for the game to specify its preferred refresh rate. So something like requestAnimationFrame(fn,refreshRate), as proposed, is necessary.

For reference, and to spur on this discussion and implementation: Since the last message I posted I've been coding on the Oculus Quest 2. It already provides a way to query the available refresh rates and set your desired refresh rate. It's incredibly pleasing and relieving to see this actually works in practise and I've been getting 120fps on the device from my WebXR code. For VR applications the refresh rate is way more critical which, I guess, is why the discussion and implementation of this feature has been accelerated and arrived on these devices already. This is how to code setting the device's maximum frame rate:

---
const gRenderer = new WebGLRenderer()
gRenderer.xr.addEventListener('sessionstart', event => {
  const gXrSession = gRenderer.xr.getSession()
  if (gXrSession.supportedFrameRates) { gXrSession.updateTargetFrameRate(Math.max(...gXrSession.supportedFrameRates)) }
  ...
}
---

gXrSession.supportedFrameRates on the Oculus Quest 2 return a Float32Array with the values [60, 72, 80, 90, 120]
Comment 19 Radar WebKit Bug Importer 2022-02-08 20:53:45 PST
<rdar://problem/88669060>
Comment 20 Simon Fraser (smfr) 2022-02-08 21:05:03 PST
Our current thinking on high frequency animations is at https://github.com/WebKit/explainers/tree/main/animation-frame-rate
Comment 21 mdrejhon 2022-08-02 20:18:26 PDT
Web Animation API is missing a mandatory capability that we require to continue to be peer-reviewed (we are in over 25+ peer reviewed papers)

We need single-framedrop detection capability (e.g. running at 59fps at 60Hz, or running at 239fps at 240Hz).  To fix this, requires an animation-frame presentation callback as part of Web Animation API, e.g. the exact (relative-time) now() moment that a frame is presented from OS to GPU driver, e.g. Present() or glxxSwapBuffers() or similar page flip / frame buffer blit is called.  

requestAnimationFrame() provides such information, while Web Animation API does not.

Because of this, Web Animation API produces lower-science-quality results, especially when a camera is pointed at a TestUFO animation (part of a NIST.gov peer reviewed paper)

Even for effects almost visible to human eye, but visible in camera photographs;

More information:
https://github.com/WebKit/explainers/issues/85#issuecomment-1203341375
Comment 22 Simon Fraser (smfr) 2022-08-02 20:35:19 PDT
> requestAnimationFrame() provides such information, while Web Animation API does not.

I'm curious about this claim. How does requestAnimationFrame() provide this information? According to the HTML spec [https://html.spec.whatwg.org/multipage/webappapis.html#event-loop-processing-model] both requestAnimationFrame() and Web Animations use the same `now` timestamp.
Comment 23 mdrejhon 2022-08-03 01:22:13 PDT
T(In reply to Simon Fraser (smfr) from comment #22)
> > requestAnimationFrame() provides such information, while Web Animation API does not.
> 
> I'm curious about this claim. How does requestAnimationFrame() provide this
> information? According to the HTML spec
> [https://html.spec.whatwg.org/multipage/webappapis.html#event-loop-
> processing-model] both requestAnimationFrame() and Web Animations use the
> same `now` timestamp.

For requestAnimationFrame(), the per-frame realtime timestamp workflow is:

1. Provide a callback function to requestAnimationFrame()

2. The callback function provides an extremely accurate refresh cycle timestamp.

These timestamps usable for detecting framedrops in FireFox and Chromium engines.  So if an animation runs only 119 frames per second at 120Hz, it is called 119 times per second.  

Collecting the timestamps show an obvious two-refresh-cycle gap (2/120sec), which allows me to detect single dropped frames instantly (in order to invalidate scientific tests)

There is no equivalent functionality I can find in Web Animation API that provides per-frame timestamps of visible frame presentation in real-time.  

If this is not documented, the Web Animation API specification need to be updated to be more clear of the existence of this functionality -- but as far as it reads, there is no similar functionality available.

A longer explanation of why Web Animation API does not yet replace requestAnimationFrame() for TestUFO needs is at:
https://github.com/WebKit/explainers/issues/85#issuecomment-1203341375
Comment 24 mdrejhon 2022-08-03 01:27:35 PDT
Additional Note (for those unfamiliar with existence of A leads to existence of B)

I should also add that it ends up being a very accurate refresh cycle timestamp by the virtue of requestAnimationFrame() being specified in W3C section 7.1.4.2.  The fact that browsers are effectively VSYNC ON means frame presentation blocks until a refresh cycle, and then immediately after, the engine calls requestAnimationFrame() callback for rendering the next frame.  The fact that it's called immediately after the refresh cycle unblocks the previous frame, means I've got scientifically accurate refresh cycle timestamps

The algorithm works correctly on Apple devices at 60Hz actually -- indeed it works correctly on Apple devices at 60Hz, but not at 120Hz (because you don't allow requestAnimationFrame to work at 120fps 120Hz in Safari)

See the Catch-22?
Comment 25 mdrejhon 2022-08-03 01:34:02 PDT
Note -- no mistake, we really want to use Web Animation API, but we need a callback extension capable of providing timestamps accurate enough to almost instantly detect single missed frames in realtime (e.g. a refresh cycle doesn't get a new frame) -- 

This is very accurate in the TestUFO engine from realtime heuristical analysis of the requestAnimationFrame() timestamps, which can be monitored in realtime at www.testufo.com/animation-time-graph (insert some CPU spikes there such as opening new tabs and intentionally slowing down the GPU -- and you will see spikes appear, and spikes that exceed half a refresh cycle are assumed to be framedrops.  Real world measurements confirm such (even with Safari 60Hz).

How can we submit a request to extend Web Animation API to meet TestUFO needs (addition of a per-frame callback function similar to requestAnimationFrame's callback function)?  We don't have to do any drawing in the callback, if that is discouraged, but we need identical timestamp quality to requestAnimationFrame for the reasons already explained at https://github.com/WebKit/explainers/issues/85#issuecomment-1203341375

We really want to use Web Animation API.  Help us out on this missing functionality in Web Animation API?
Comment 26 mdrejhon 2022-08-03 20:15:11 PDT
Question: How can we submit a proposal to add a real-time frame-presentation timetamp callback feature to Web Animation API?   (similar to the 'callback' feature of requestAnimationFrame)

Pre-requisites:
- Callback is executed everytime a frame is successfully visibly presented to display.
- Callback function either receives a timestamp parameter (preferred) or I can execute now() at top of function (backup plan)

Since all web browsers are inherently VSYNC ON technology, callbacks during full framerate=Hz operation defacto aligns automatically to real-world refresh cycle timestamps (to within 100 microseconds on Chrome on an RTX card, and to within 1 millisecond on 60Hz Apple Macs).

But since requestAnimationFrame is being deprecated (and does not support 120Hz anyway), I need a path.

Help me; how can I help the standardization?

Help me; how can I help Apple sell 120Hz?  

TestUFO is the world's most popular 120Hz-showoff demo.
Comment 27 Simon Fraser (smfr) 2022-08-03 20:21:54 PDT
With the Web Animations API proposed at https://github.com/WebKit/explainers/tree/main/animation-frame-rate, where you can create an animation that will give you a JS callback on every frame, you'll be able to get exactly the same information you can get with requestAnimationFrame(), at least in WebKit.

If other browsers are passing a timestamp to requestAnimationFrame() which is not just the "now" timestamp from the HTML spec, and this different timestamp gives you additional information, then you should lobby for those browsers to standardize whatever they are doing.
Comment 28 mdrejhon 2022-08-04 05:08:16 PDT
Thanks for the tip, I need to study if our team is incorrectly using the new APIs, or if we've discovered a major inconsistency between browsers in their timestamp handling between different browsers in Web Animation API  (far more inconsistent than requestAnimationFrame).  

We will now do further research on a wider number of browsers.

However, a scientific correction:

> If other browsers are passing a timestamp to requestAnimationFrame() which is not just the "now" timestamp from the HTML spec, and this different timestamp gives you additional information, then you should lobby for those browsers to standardize whatever they are doing.

Actually -- it's the same thing when it hits an equilibrium of framerate=Hz.

Buring framerate=Hz situation, now() automatically settles to an equilibrium where now() is identical to refresh cycle time.   One and the same thing, during max frame rat, it becomes is identical in the callback.  It's a synonym during framerate=Hz

now() is synonymous with refresh cycle timing when framerate=Hz, because of the way VSYNC (which existed since 1920s Biard/Farnsworth analog TVs) is a defacto comma-separator between refresh cycles.  

(VSYNC = Vertical Synchronization = a separator between refresh cycles, generated by all analog and digital video outputs over the last 100 years).  Apple terminology sometimes call this BeamSync or displaySyncEnabled, but they're all synchronized to the VSYNC signal in the GPU -- it's the refresh cycle metronome.

VSYNC is how Apple/Windows/Android/iOS synchronizes framerate=Hz for things like smooth scrolling and jank-free animations.

SITUATION 1
When (framerate != Hz), it deviates so much that it signals instantly like a christmas tree within 1/Hz (i.e. reliable missed frame detection logic is easy to write with requestAnimationFrame().  The interval jitters, e.g. a dropped frame is 2/Hz sec between timestamps rather than 1/Hz sec between timestamps.

SITUATION 2
When (framerate == Hz), it settles into an equilibrium that almost perfectly relative-time aligns to the VSYNC in the GPU (to an error margin of +/- 0.1 to 1ms at https://www.testufo.com/animation-time-graph ...) and it is easy to automatically decide that it's the current display refresh rate, because the interval doesn't jitter at all.

Because of the fact that scientific equilibrium (2+2=4 is always true independently of OS), now() is identical to refresh cycle timestamps during SITUATION 2.   Refresh rate detection is reliable in requestAnimationFrame() 

The way VSYNC ON in many APIs (VSYNC ON, VertSync ON, InVBlank=true, BeamSync ON, or whatever API terminology is used) -- works is that it blocks frame presentation (all APIs in all OS that synchronizes to the 100-year-old VSYNC that exists in all analog and digital video signals -- it's a 100% OS and vendor independent sync).  So, when things are running maxed-out, timestamps almost perfectly aligns to refresh cycles.  It's just scientific certainity, like 2+2=4, so in the spec, "now()" is identical to "refresh cycle timestamps" simply because of science of VSYNC.

Conculsion: There is nothing to change in the requestAnimationFrame() standard, as it works perfectly now in all major HTML5 browsers (even in Safari too, at least at 60Hz).  I'm kind of surprised you mentioned that, but perhaps it was from your unfamiliarity with a 100-year-old refresh cycle separator signal -- but at least now you know now() in the callback is generally synonymous to refresh cycle timestamps when things are running flat-out max framerate.

That's why we're able to do refresh cycles so precisely in TestUFO, because we're very familiar with the VSYNC science (Blur Busters specializes in the Present()-to-Photons black box).
Comment 29 mdrejhon 2022-08-04 05:14:34 PDT
Update, I now realize you meant Web Animation API rather than requestAnimationFrame():

> If other browsers are passing a timestamp to WEB ANIMATION API which is not just the "now" timestamp from the HTML spec, and this different timestamp gives you additional information, then you should lobby for those browsers to standardize whatever they are doing.

Perhaps that is the new insight. While requestAnimationFrame is working perfectly with correctly synonymous now()=refresh timestamps in all major browsers (except 120Hz Safari -- that is when we pull hair & throw keyboards)

You're right -- we may have just very well discovered an inconsistency between different browsers' handling of Web Animation API timestamps.  We now need to test all majors and see why it deviates from behavior of requestAnimiationFrame in non-synonymous "now() identical to refresh cycle timestamp" behavior, since that's literally just 2+2=5 in VSYNC science...
Comment 30 Simon Fraser (smfr) 2022-08-04 11:33:42 PDT
(In reply to mdrejhon from comment #29)
> Update, I now realize you meant Web Animation API rather than
> requestAnimationFrame():
> 
> > If other browsers are passing a timestamp to WEB ANIMATION API which is not just the "now" timestamp from the HTML spec, and this different timestamp gives you additional information, then you should lobby for those browsers to standardize whatever they are doing.

No, I did mean requestAnimationFrame().
Comment 31 mdrejhon 2022-08-04 12:21:13 PDT
OK, in that case, Comment 38 automatically applies
( https://bugs.webkit.org/show_bug.cgi?id=173434#c28 )
There's no change needed to requestAnimationFrame standard except for lack of 120Hz Safari iOS support, because now() is scientifically synonymous with refresh cycle timestamps whenever it settles into a framerate=Hz equilibrium.
Comment 32 mdrejhon 2022-11-22 18:34:35 PST
Fantastic to see 120Hz Safari working perfectly on the MacOS platform now, as long as you disable the 60fps lock setting.  Once you disable that, requestAnimationFrame() works perfectly in TestUFO at 120Hz.   

Thank you for unlocking that, whomever did it.

Now, please do the same thing on iPadOS and iOS, at least as an optional feature.
Comment 33 Matt Perry 2023-08-10 03:07:08 PDT
(In reply to Simon Fraser (smfr) from comment #20)
> Our current thinking on high frequency animations is at
> https://github.com/WebKit/explainers/tree/main/animation-frame-rate

Can you confirm this is still your current thinking? The document seems out of date and if it isn't, most of the points raised seem tenuous:

> We propose adding a frameRate property on the Animation interface

requestAnimationFrame (rAF) is explicitly for circumventing the limitations of Animation. The example in the spec is canvas-based for a reason https://html.spec.whatwg.org/multipage/imagebitmap-and-animations.html#animation-frames

> WebKit chose to restrict web content updates to 60Hz for two reasons: first, we measured a significant increase in power usage

I wonder if you have the stats to back this up, but my intuition is that most calls to rAF are via popular animation libraries like GSAP and Framer Motion. The document proposes alternatives to rAF that, if widely adopted, would draw the same amount of power. If these high framerate alternatives exist, animation libraries will immediately make use of them. Throwing the battery life argument out the window.

>  second, we found several examples of web pages that had incorrect behavior when requestAnimationFrame() callbacks were fired at a non-60Hz frequency.

Safari is only 25% of browser usage. Other browsers support vsync rAF. Most modern screens are 120/144hz.

The main example of animations that would break are the typical "hello world" animation examples of the nature `rotate += 1`. It is, of course, bad practise to write this kind of animation even with a locked framerate, as slowdowns can happen.

However, given Safari's relative market share, is it not more likely that the people writing these fundamentally broken examples have done so in Chrome, and are now more likely to be surprised to find their spinning 3D cube moving at half speed in Safari? 

You can take this fundamental principle and apply it to all your examples of "incorrect behaviour" and they'll increasingly be showing incorrect behaviour *only* in Safari. 

> There is generally two categories we see where the authors would want to specify an intent to update at a rate different than the default.

Absent: syncing physical motion of canvas/3D etc to scroll or 120fps HTML elements.

> WebKit is dedicated to push the concept of Custom Effects forward

Are they? The spec looks abandoned and its suggested to be replaced with an onUpdate callback. I like the idea of a CustomEffect, I like the API, and it's clearly superior than an onUpdate callback tied to an arbitrary animation. However I also don't understand how either address your own complaints about battery life.
Comment 34 mdrejhon 2023-08-10 17:58:24 PDT
FYI, for those unaware,

requestAnimationFrame() now works at 120fps on Apple iPads.

If it is not working at 120fps, then do:

Settings -> Safari -> Advanced -> Experimental Features -> "Prefer Page Rendering Updates near 60fps"
Comment 35 Matt Perry 2023-08-11 01:43:43 PDT
(In reply to mdrejhon from comment #34)
> FYI, for those unaware,
> 
> requestAnimationFrame() now works at 120fps on Apple iPads.
> 
> If it is not working at 120fps, then do:
> 
> Settings -> Safari -> Advanced -> Experimental Features -> "Prefer Page
> Rendering Updates near 60fps"

It's an interesting curio but not something I can reasonably tell my users when they ask why scroll-linked animations look terrible in Safari
Comment 36 mdrejhon 2023-08-11 17:17:49 PDT
I totally agree.

Apple needs to make this easier, even if it's a permission-based API.  Similar to the permission prompt for certain things (e.g. storage, full screen mode, etc).

_______________________

PERMISSION PROMPT

This webpage is requesting high-performance animations at frame rates above 60fps. This can result in smoother animations, but will consume more battery power.

[Allow] [Deny]
Comment 37 Matt Perry 2023-08-14 01:54:55 PDT
I also have to call further into question the claim that the Webkit team has discovered instances where changing the tick rate of requestAnimationFrame broke behaviour on certain webpages. If this were true, or of genuine concern to the team, then why is it also the case that Webkit throttles rAF to 30fps in low power mode and within iframes? It seems to me the team has already accepted the variable-rate nature of rAF.
Comment 38 mdrejhon 2023-11-30 14:47:03 PST
> I also have to call further into question the claim that the Webkit team has discovered instances where changing the tick rate of requestAnimationFrame broke behaviour on certain webpages. If this were true, or of genuine concern to the team, then why is it also the case that Webkit throttles rAF to 30fps in low power mode and within iframes? It seems to me the team has already accepted the variable-rate nature of rAF.

Hello. Allow me to tell you Apple's stance as Simon Fraser explained to me:

1. High frame rate animations eat lots of power.  That is understandable.  

SOLUTION: The user can fix this by exiting Low Power Mode.  I am 100% completely fine with this, because the user CAN turn off Low Power Mode temporarily, if they urgently need 120fps for demos ("This is WHY you need to buy a 120Hz iPad")

2. IFRAME 30fps is to prevent advertisement banners eating too much power.

SOLUTION: Unresolved and unoverrideable by user.  This is a point of contention for me.  I would like a "Same-origin" exception or a configurable option/permissions for this, because I do TestUFO EMBEDs like at https://blurbusters.com/oh-no-im-at-the-wrong-refresh-rate/ ... It shows the correct display refresh rate for Windows but the wrong refresh rate for Apple.  This confuses Apple users.  

RECOMMENDED SOLUTION: Apple should find a way to add a setting to allow users to override this, at least for same-origin.
Comment 39 mdrejhon 2023-11-30 14:53:31 PST
*** UPDATE ***

requestAnimationFrame() has a bug at both 60Hz and 120Hz on any 144Hz display connected to a Mac Mini or a MacBook.

TestUFO animations stubbornly run at 60fps (stutters bad) or 120fps (stutters bad). Since 144 is neither divisible by 60 nor 144.

So when "Limit to 60fps" is disabled, it changes to a limit of 120fps!  This is bad, because this stutters very badly when ProMotion is turned off.   

Apple should remove the 120fps whisper cap from requestAnimationFrame() as the MacOS experience is absolutely terrible with external gaming monitors attached.  As Apple starts courting more gamers, including Vision Pro, many of its develoeprs (who do VR) already have high-Hz monitors, and are TestUFO users, and are finding TestUFO performs bad for some unknown weird reason.

I am successfully showing off TestUFO at perfect 540fps at 540Hz, and Apple employees visited BOE booth at DisplayWeek 2023, and TestUFO was running www.testufo.com/framerates-versus on a laptop connected to their 500Hz LCD display.  Perhaps Apple WebKit employees should talk to those Apple Display people, as I chatted to those Apple employees about my bone of contention of 120Hz requestAnimationFrame() ... TestUFO now has ~2 million visitors per month, by vendors, manufacturers, researchers.

Independently, I approached a few employees of display vendors at other conventions I visited.  TestUFO is also used by the manufacturer (including FoxConn) of Apple's displays too, to show off to interns why 120Hz looks so much better, etc.
Comment 40 mdrejhon 2023-11-30 14:54:30 PST
Ooops, I meant "....divisible by 60 nor 120".  
(I wish this system would let me edit comments, like Bugzilla or GitHub Issues)
Comment 41 mdrejhon 2023-11-30 15:08:55 PST
BTW, the upcoming TestUFO HDR 2.0 supports Safari DCI-P3 !!! (And Rec.2020/2100)
Including display tests capable of brighter-than-white using a video workaround algorithm I've come up with.

Screenshots:


So, please (PLEASE), fix requestAnimationFrame 144Hz+ support for MacOS when user disables the 60fps limit.

If you want to come visit me at CES 2024 to discuss the implications -- I'll be at the NanoSys-SHOEI booth, and I'd be happy to demonstrate TestUFO 2.0 on an iPad Pro 120Hz XDR in person.  Contact mark [at] blurbusters.com  ... A lot of booths are using TestUFO in fullscreen mode, so anytime Apple has visited a display convention, they already saw TestUFO at some booths (without the TestUFO brand).

TestUFO HDR 2.0 pre-announcement with brighter-than-white photo:

https://github.com/blurbusters/testufo-public#readme
Comment 42 mdrejhon 2023-12-20 20:56:44 PST
BTW
I have open sourced our HTML5 refresh rate calculator at:
https://github.com/blurbusters/RefreshRateCalculator

Apache 2.0 license -- you're welcome -- commercialize away

It's the same refresh rate calculator used by vsynctester.com and testufo.com and is the world's most accurate browser-based refresh rate calculator algorithm for most platforms.  It even correctly detects 600Hz-1000Hz prototype monitors connected to Windows platform (I'm Blur Busters, so I work with display manufacturers).  

It is accurate on Apple to about 60Hz unless "Limit Animations To 60fps" is disabled, then it's accurate to about 120Hz.  If you connect a 144Hz-240Hz monitor to an Apple system, it fails.
Comment 43 mdrejhon 2023-12-26 14:08:35 PST
Created attachment 469213 [details]
Accidentally misleading tooltip by Safari Browser on MacOS

A (potentially accidentally misleading/accidentally deceptive) tooltip by Apple;

The screenshot claims matching refresh rate, but this tooltip is false when connecting a monitor of a refresh rate above 120Hz.  For example, a 144Hz monitor will always permanently stutter at 60fps and 120fps, since 144 is not divisible by 60, and because of a hidden frame rate cap built into Apple Safari.

With 60 vs 120 vs 240 massively more mainstream visible on OLED with its fast pixel response, I think Apple needs to either (A) correct the tooltip to say that frame rate will still be capped to 120, or (B) remove the Safari internal whisper cap of 120 for any refresh rate above 120.
Comment 44 Jeffrey Blanz 2024-04-12 05:35:56 PDT
To update this bug:

- 120hz animations are supported on macOS and iPadOS.

   - Above 120hz animations are not supported on macOS with an external monitor with over a 120hz refresh rate. Other browsers support up to 240hz, for example.

- 120hz animations are not supported on iOS.

- 90hz animations are supported on visonOS

Summary:

1. iOS needs to support 120hz animations

2. macOS needs to support up to 240hz animations.
Comment 45 Jeffrey Blanz 2024-04-12 05:57:01 PDT
To update this bug (again):

- 120hz animations are supported on macOS and iPadOS.

   - Above 120hz animations are not supported on macOS with an external monitor with over a 120hz refresh rate. Chrome/firefox browsers support unlimited refresh rate animations. (Although currently the highest refresh rate monitor has 500hz).

- 120hz animations are not supported on iOS.

- 90hz animations are supported on visonOS.

Summary:

1. iOS needs to support 120hz animations.

2. macOS needs to support up to unlimited animations.

3. The feature flag “prefer page rending updates near 60fps” needs to be off by default for macOS, iOS, and iPadOS. It is already off by default for visionOS.

Also, if anyone knows of a PWA that can test screen hz/fps with vsync like testufo.com can, a comment would be appreciated. PWA are currently capped at 60hz animations because the feature flag “prefer page rending updates near 60fps” is on by default for iOS, iPadOS, and macOS. PWAs only run on system default flags.