-
Notifications
You must be signed in to change notification settings - Fork 386
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
Behavior of window.requestAnimationFrame and window.requestIdleCallback when presenting #225
Comments
As noted in this Chromium commit, there may be a race condition between the window rAF and the beginning of the WebVR mechanism. Whatever the outcome of this issue, we should ensure the behavior is clearly defined and that there is a reliable path for authors. |
Quick update: This was discussed on the WebVR implementors call today and the general consensus is that if the page isn't visible it shouldn't be pumping rAF. (Didn't discuss rIC as much, because not everyone implements it.) In the future exceptions would probably need to be made for DOM content that is displayed in VR via a layer or similar mechanism, but at that point it's reasonable to expect that the DOM compositor will have to be running to generate that content anyway, and rAF will naturally run as a result. Some questions came up about what framerate the rAF should run at in that scenario (monitor vs. HMD?) but if the in-VR layer was able to be updated asynchronously from headtracked rendering on the quad it wouldn't be a user comfort issue. |
Also, as a follow-up from the WebVR implementers call, we wish to avoid any artifacts related to video framerate if parts of the page are mirrored into the headset. For example, if 24fps video was rendered in an HTMLVideoElement it is temporally upsampled to the 2d monitor's 60hz framerate. This is commonly done by repeating some frames, causing a variability in frame duration as the 24hz video catches up to the 60hz output rate. Effectively, half of the video frames are presented for 2 vsync cycles and the other half of the video frames are presented for 3 vsync cycles:
If a piece of the page, containing such a video is then sampled into a VR layer at 60hz, it will be again upsampled. A VR display could be running at 90hz typically:
If we were upsampling the video directly from 24hz to 90hz:
|
The video frame uniformity issues would also apply to CSS animations and WebGL canvases that will be projected onto "floating quad in space" layers or onto textures within the VR presentation. I believe we should always prioritize the VR experience when a VR presentation is active. The key question should be if the effective framerate of the 2d page should bump up to the HMD's framerate in the event that parts of it are captured for VR presentation, or if it should remain at 60hz. This might not be a simple task for browser implementers, and could slow adoption for the WebVR 2.0 API if required. If the video frame uniformity is the issue affecting users the most, perhaps we should first implement a specialized video VR layer or implement optimized functions for decoding video directly to WebGL textures. |
Regarding the "requestIdleCallback", there may be issues with running that out-of-sync from the normal XR framerate, as effectively there would be "idle" work happening during the period of a XR frame that would not be ideal, such as when the VR compositor is performing the hard-realtime task of compositing asynchronously transformed / warped layers at vblank. For many (most?) tracked XR headsets, the "requestIdleCallback" would ideally occur immediately after this vblank interval occurs (often signaled by lower level api's blocking until this ideal time). One reason that XR sites themselves would want to use "requestIdleCallback" is to move non-rendering tasks outside of "requestAnimationFrame" so that the XR runtime environment can optimize the start of "requestAnimationFrame" based on prior frame times. The goal of such systems include moving the rendering as late as possible to ensure the least work done by the reprojection (less delta time between actual frame display and the predicted pose). If idle work, such as managing game state, updating physics, and playing audio also occurs within "requestAnimationFrame" and there is no longer a "submit" call like in WebVR, the precise time needed for the rendering phase of the frame can not be inferred. One solution is to have a "requestIdleCallback" added to the XRFrame, triggered some time in the frame after the "requestAnimationFrame". Another would be to re-introduce the "submit" call on the XRWebGLLayer and have it return a promise that resolves when the rest of the per-frame processing can continue. |
Caveats: Synchronizing window raf to XRSession raf would preclude any possibility of multiple simultaneous XRSessions for separate devices with un-aligned frames or varying frame rates. Alternate solution: Sync window.requestIdleCallback to XRSession but not alter window.requestAnimationFrame |
Addressed half of #225. Indicates that there's no relationship between window.rAF and session.rAF, but also makes it clear that immersive sessions may prevent window.rAF from running in some circumstances.
Addressed half of #225. Indicates that there's no relationship between window.rAF and session.rAF, but also makes it clear that immersive sessions may prevent window.rAF from running in some circumstances.
The exact desired behavior is unclear, see immersive-web/webxr#943 and immersive-web/webxr#225
The exact desired behavior is unclear, see immersive-web/webxr#943 and immersive-web/webxr#225
The exact desired behavior is unclear, see immersive-web/webxr#943 and immersive-web/webxr#225
The exact desired behavior is unclear, see immersive-web/webxr#943 and immersive-web/webxr#225
The exact desired behavior is unclear, see immersive-web/webxr#943 and immersive-web/webxr#225
Automatic update from web-platform-tests Update webxr timestamp test to not compare against window.rAF() The exact desired behavior is unclear, see immersive-web/webxr#943 and immersive-web/webxr#225 -- Fix xrDevice_requestSession_no_mode to test for a throw, not a rejection -- Allow spawning inline sessions without interaction -- wpt-commits: be18a267fd4eaac9228ce681c68b3f7fa73d19e3, e9a537ff548399c0ff48f4d554081a86af30fb56, 39bacd5cc2180c62ca0468e646be16f81f353f28 wpt-pr: 20737
Automatic update from web-platform-tests Update webxr timestamp test to not compare against window.rAF() The exact desired behavior is unclear, see immersive-web/webxr#943 and immersive-web/webxr#225 -- Fix xrDevice_requestSession_no_mode to test for a throw, not a rejection -- Allow spawning inline sessions without interaction -- wpt-commits: be18a267fd4eaac9228ce681c68b3f7fa73d19e3, e9a537ff548399c0ff48f4d554081a86af30fb56, 39bacd5cc2180c62ca0468e646be16f81f353f28 wpt-pr: 20737 UltraBlame original commit: c6dbb106ae576d0dae4ef26b2de2a6d892ec3880
Automatic update from web-platform-tests Update webxr timestamp test to not compare against window.rAF() The exact desired behavior is unclear, see immersive-web/webxr#943 and immersive-web/webxr#225 -- Fix xrDevice_requestSession_no_mode to test for a throw, not a rejection -- Allow spawning inline sessions without interaction -- wpt-commits: be18a267fd4eaac9228ce681c68b3f7fa73d19e3, e9a537ff548399c0ff48f4d554081a86af30fb56, 39bacd5cc2180c62ca0468e646be16f81f353f28 wpt-pr: 20737 UltraBlame original commit: c6dbb106ae576d0dae4ef26b2de2a6d892ec3880
Automatic update from web-platform-tests Update webxr timestamp test to not compare against window.rAF() The exact desired behavior is unclear, see immersive-web/webxr#943 and immersive-web/webxr#225 -- Fix xrDevice_requestSession_no_mode to test for a throw, not a rejection -- Allow spawning inline sessions without interaction -- wpt-commits: be18a267fd4eaac9228ce681c68b3f7fa73d19e3, e9a537ff548399c0ff48f4d554081a86af30fb56, 39bacd5cc2180c62ca0468e646be16f81f353f28 wpt-pr: 20737 UltraBlame original commit: c6dbb106ae576d0dae4ef26b2de2a6d892ec3880
Automatic update from web-platform-tests Update webxr timestamp test to not compare against window.rAF() The exact desired behavior is unclear, see immersive-web/webxr#943 and immersive-web/webxr#225 -- Fix xrDevice_requestSession_no_mode to test for a throw, not a rejection -- Allow spawning inline sessions without interaction -- wpt-commits: be18a267fd4eaac9228ce681c68b3f7fa73d19e3, e9a537ff548399c0ff48f4d554081a86af30fb56, 39bacd5cc2180c62ca0468e646be16f81f353f28 wpt-pr: 20737
Addressed half of immersive-web#225. Indicates that there's no relationship between window.rAF and session.rAF, but also makes it clear that immersive sessions may prevent window.rAF from running in some circumstances.
|
I think we want to conclude with something like "requestAnimationFrame / requestPostAnimationFrame / requestIdleCallback do not fire when the 2d browser view is not visible. When the 2d browser view is visible simultaneously with the immersive XR session, they may fire at different framerates and with differing sub-frame timing." |
For We can still guarantee that "You can call requestIdleCallback() within an idle callback function to schedule another callback to take place no sooner than the next pass through the event loop.", even when the 2d display is hidden. Perhaps some non-normative text could be added to describe "Pages should make no assumption that a callback passed to |
As this intersects some other standards, such as CSS and WebGL, we should consult with those groups before closing this issue. |
Hi, But if its necessary for the app to function properly.... XR Tracking should only influence what portion of any kind of content you are seeing. I'ts just a different View for the same content, possbly with higher frame rate. I learned at university to try to decouple View and Logic. IMHO Disabling the rAF of an app that youre tring to present is possibly altering the experience main behaviour on certain devices and thus contradicts the whole paradigm of a hardware agnostic API like WebXR. |
I think this is the right way to go forward here. @toji, think we should helpwanted this? |
- This makes animations continue to work while in XR/VR/AR because requestAnimationFrame() was attached to the main window. - See immersive-web/webxr#225
Short and sweet: When we're in WebVR presentation mode on devices without an external display, should the page continue pumping the window rAF and rIC loops?
For context: In Chrome at least when we kick into VR mode on mobile we stop the main page from running it's normal compositing process for performance reasons. This has a natural side effect of preventing rAF and rIC from running unless we take explicit (and slightly hacky) steps to avoid that. It may make sense, though, to treat this like any other time we hide the page (switching tabs, etc.) and suspend rAF simply because the page isn't actually meant to be updating and rAF is meant to be tied to page animation. (I'm not as sure about the intended behavior for rIC.)
That would create a behavioral disparity with desktop, though, which WILL have the page visible while presenting and does want to keep rAF running. That could create a situation where developers test code primarily on one platform and are surprised by the behavior of the others.
Would love opinions on this from other vendors!
The text was updated successfully, but these errors were encountered: