AF Manager class for dynamic animation frame request/cancel#1407
AF Manager class for dynamic animation frame request/cancel#1407gkjohnson merged 39 commits intoNASA-AMMOS:masterfrom
Conversation
gkjohnson
left a comment
There was a problem hiding this comment.
Great, thanks! A couple comments but I think this is the right direction
| @@ -0,0 +1,43 @@ | |||
| class AFManager { | |||
There was a problem hiding this comment.
Lets call this FrameScheduler for now.
| setXRSession( xrsession ) { | ||
|
|
||
| this.xrsession = xrsession; | ||
|
|
||
| } | ||
|
|
||
| removeXRSession() { | ||
|
|
||
| this.xrsession = null; | ||
|
|
||
| } |
There was a problem hiding this comment.
When changing the system being used for callbacks we will have to cancel all previous callbacks and reregister them with the new function. Eg if the "LRUCache" schedules an unload event it will be waiting until that event fires before scheduling another one. So if the last event is scheduled using the "xrSession" callback and then the session closes, the scheduled callback will never be fired.
So we'll need to keep track of all scheduled callbacks and rAF handles to swap over the scheduled events.
|
@phoenixbf - just wanted to check in to see if you had any more questions on the changes needed here. |
Hi, performing some local testing in order to have a clean rAF tracking system and handling swaps |
|
I've added management of pending AF. So far I tried the above logic in both local and online setups without any evident issues, also with mutiple tsets. If this is the right direction, it should be probably instantiated in |
|
Thanks the direction of this looks great. I think we can cut down on some code redundancy in the implementation but we can deal with that once everything is working.
This sounds good to me. Looks like the "LRUCache", "PriorityQueue", the "throttle" function, and "QueryManager" are all places where rAF is used (though the throttle function can maybe be changed to "queueMicrotask") |
…ryManager; updated Dingo Gap VR sample
gkjohnson
left a comment
There was a problem hiding this comment.
Looking good! Made a few comments -
|
|
||
| setXRSession( xrsession ) { | ||
|
|
||
| if ( ! this.framescheduler ) return; |
There was a problem hiding this comment.
this should never be "null" so we should be able to remove this check.
| this.isLoading = false; | ||
|
|
||
| // FrameScheduler referenced by LRUCache, PriorityQueue | ||
| this.framescheduler = new FrameScheduler(); |
There was a problem hiding this comment.
lets use camel casing to align with the class naming:
this.framescheduler -> this.frameScheduler|
|
||
| this._unloadPriorityCallback = null; | ||
|
|
||
| this.framescheduler = null; |
There was a problem hiding this comment.
Lets initialize these to new FrameScheduler() so the classes are in a usable state when constructed. Then we can remove the null checks, as well. This should help the tests pass, too.
- remove unused function - remove use of "window" - ensure "flushPending" clears all pending handles - code style update
|
I've just made some of the remaining changes to fix tests, add new tests for FrameScheduler, and address some code styling and other issues. I think this should be ready to merge but if you could test it in a real XR environment that would be great. |
Yep, sure. Today I'll carry out additional online tests with a few HMDs |
Not sure if I understand the last paragraph. I mean rAF is fired always, even if you have other windows in Meta quest open. What's interesting is that, both window.requestAnimationFrame and xrsession.requestAnimationFrame are fired by the frame scheduler, whether your session has visibilityState "visible" or "visible-blurred". I made a video to illustrate the problem. Have a look at it: https://drive.google.com/file/d/12ZfhMkAjkJPxaYLlh30wFM-1iiOrX0Fw/view?usp=sharing (cannot attach to GitHub, size exceeds GitHub limits). I'm not good at it but I can make more videos, if you need, feel free to give me concrete instructions. In the video, you can see how the imagery is not applied at all and how there are very few calls to both rAF, when I was in VR, or better say visibilityState was "visible". Once I press the meta button on the controller, the session visibilityState changes to "visible-blurred" and you can see how many rAF are fired (both window and xrsession). Once I toggle the state (from "visible" to "visible-again"), there are very few rAF calls. |
Yeah lets just make this a singleton for now. I'm open to suggestions but we can manage it like so: import { FrameScheduler } from '3d-tiles-renderer';
FrameScheduler.requestAnimationFrame( ... );
FrameScehduler.setXRSession( ... )
The window's "requestAnimationFrame" will have to fire when the "window" is visible so content in just the window, like DOM, can be updated. And the xr session rAF will have to be fired when the XR session is presenting so content can be updated for the XR view. If the XR rAF didn't fire while the background was rendering then it would just freeze and the camera view would not be able to update, either. So what we're seeing are the following situations when the presenting === true (the xr session is running):
What I'm wondering is if there is every a situation we can get into where the "presenting" is true (eg sessionstart has fired & sessionend has not) and the window rAF is firing while the xr session rAF is not (this would be a line with "false | true" on the above table). If we think there is or there may be in the future then we should make sure we account for this in our FrameSchduler implementation. Otherwise this will happen again and it's quite a hard issue to understand the track down. Relatedly, I'd appreciate it if you could make any issue at the meta emulator and link it here so we can more easily understand and test this behavior:
--
I can't read any of the text in this video with the compression, unfortunately, so I can't fully understand what its showing. |
I see, now that makes much more sense. Thanks a lot!! Your table basically summarized what I did in the video. Though some window.rAF are called even in the immersive view (perhaps this is some other part of the library). I don't know why Google drive still hasn't provided a better quality video. Anyway, I'm not sure if one can reproduce a situation where the renderer.xr is presenting, the window.rAF is fired, while xrsession.rAF is not fired. (I can't really think of any good example) If you look at the WebXR specification, 4.3 (links to the highlighted part), they discourage to use window.rAF in the context of xrsession because "the timing of callbacks of window.rAF may not coincide with xrsession.rAF". Though there is some sort of the pattern they suggest using for "transition between these two types of animation loops ". So, I would rule out the use case where you solely use window.rAF while renderer.xr presenting. I think referring to the WebXR specification is a good justification. However, I'm thinking that maybe the frame scheduler could also use a third option, |
I'm not sure what you mean by this? The classes using frame scheduler need to run every frame and setTimeout is not guaranteed to do so. It may run multiple times per frame or not at all depending on the platform and the framerate. |
|
Hi there, |
|
Thanks @phoenixbf - I'll take a deeper look this weekend and make a few more changes I've had in the back of my mind. It looks like one of the tests is failing, though. Would you be able to take a look? |
|
I've made a few changes - primarily changing the class to use all static functions and using it as a singleton everywhere. The class has also been renamed to "Scheduler" and I've removed the "setXRSession" function from "TilesRenderer" so you set it like so: import { Scheduler } from '3d-tiles-renderer';
Scheduler.setXRSession( session );I'll merge this but if you could test it and follow up if there are any issues that would be great! Thanks again for your help in tracking down the issue and coming up with a solution. |
Thanks, I'll test these ASAP on my XR equipment |
|
just to confirm I tested several online tilesets on different equipment (Meta Quest 2, Meta Quest Pro and Hololens 2) without issues |
See #1342