Often times for animations you want to be able to throttle rendering at some specific speed (ex: 60fps). However, there is no clear way to achieve this with wasi-gfx
Notably, the get-frame returns an empty object
subscribe-frame: func() -> pollable;
get-frame: func() -> option<frame-event>;
record frame-event {
/// TODO: This field doesn't mean anything.
/// Can't have empty record. Would like to have a way around this.
nothing: bool,
}
Notably, from a Javascript host, you actually can get the timestamp from requestAnimationFrame as the first argument to the callback as per the docs
subscribeFrame() {
const pollable = new Pollable();
const onFrame = () => { // <- note: timestamp argument ignored
this.frameEvent = {
nothing: false,
};
pollable.resolve(); // <- we could be passing the timestamp in here
requestAnimationFrame(onFrame);
};
requestAnimationFrame(onFrame);
return pollable;
}
Without the timestamp argument, requestAnimationFrame will run depending on the user's monitor's refresh rate (so your animation may run over 2x faster for some users!)
Alternative solution
Although from the Javascript host the timestamp is easy to get, maybe that's not the same for every host (although it would be a bit surprising to have a host that can't tell its own clock time)
An alternative, to ensure the host has a clock functionality, would be to rely on wasi-clocks. Although this works, there are two issues with this:
- Hard hit desired fps.
requestAnimationFrame for example runs depending on the user's monitor, so if you want your animation to run at 20fps, it won't work well if the user's monitor is 144hz as 144 is not a multiple of 20. This means you need to round, causing some frames to be slightly longer/shorter than others
- Hard to synchronize updates between multiple wasi-gfx apps running.
requestAnimationFrame gives the same timestamp to all listeners, whereas wasi-clock skews based on render time of other apps (ex: imagine you have two apps A and B. A takes 5ms to render. That means that B's wasi-clock will be 5ms later than what A saw)
Often times for animations you want to be able to throttle rendering at some specific speed (ex: 60fps). However, there is no clear way to achieve this with
wasi-gfxNotably, the
get-framereturns an empty objectsubscribe-frame: func() -> pollable; get-frame: func() -> option<frame-event>; record frame-event { /// TODO: This field doesn't mean anything. /// Can't have empty record. Would like to have a way around this. nothing: bool, }Notably, from a Javascript host, you actually can get the timestamp from
requestAnimationFrameas the first argument to the callback as per the docsWithout the timestamp argument,
requestAnimationFramewill run depending on the user's monitor's refresh rate (so your animation may run over 2x faster for some users!)Alternative solution
Although from the Javascript host the timestamp is easy to get, maybe that's not the same for every host (although it would be a bit surprising to have a host that can't tell its own clock time)
An alternative, to ensure the host has a clock functionality, would be to rely on wasi-clocks. Although this works, there are two issues with this:
requestAnimationFramefor example runs depending on the user's monitor, so if you want your animation to run at 20fps, it won't work well if the user's monitor is 144hz as 144 is not a multiple of 20. This means you need to round, causing some frames to be slightly longer/shorter than othersrequestAnimationFramegives the same timestamp to all listeners, whereaswasi-clockskews based on render time of other apps (ex: imagine you have two apps A and B. A takes 5ms to render. That means that B's wasi-clock will be 5ms later than what A saw)