[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Public WebGL] frame timing and continous scaling



Sorry for the long delay replying. Dealing with WebGL stability bugs on newly deployed automated test machines.

Have talked with a couple of folks who work on Chrome's scheduler, which decides when to fire requestAnimationFrame callbacks, among other things. Some observations but no firm conclusions yet. I'd like to avoid posting my half-baked thoughts here, so let me continue to discuss with these folks off-list and we'll post some conclusions afterward.

Thanks,

-Ken


On Sun, Jun 7, 2015 at 1:33 AM, Florian Bösch <pyalot@gmail.com> wrote:
Oh, also if the browser doesn't  do even frame division stepping, then 60fps is the only synchronized display frequency. So even if you skip rAFs, you will not be 30fps synchronized, and so you'll get a lot of microstuttering/jittering/frame-tearing. Aiming at 60fps is really the only method to get even a chance to avoid all that.

On Sun, Jun 7, 2015 at 9:52 AM, Ben Adams <thundercat@illyriad.co.uk> wrote:
Could you could throttle to 30fps by skipping any work in a rAF that is < 30ms of the end of previous rAF?


On 7 June 2015 at 08:43, Florian Bösch <pyalot@gmail.com> wrote:
Investigating this issue a bit more I came to some conclusions. I've also extended the test tool to measure/display both interframe time (grey) and intraframe time (red) and added options for different synchronizing methods. The conclusions first, the observational evidence after.
  • In order to avoid going below 60fps where all the microstepping and degradation dragons live, it's required to know when that would happen.
  • I have proposed to solve that problem with an API, but the resonance from UA vendors is neglible, and so I have to assume it's going to take considerable time (if ever) when that issue gets addressed (wtg here WebGL, competing with native platforms, naaat)
  • In lieu of a solution emerging, it's up to JS app developers to get around that problem somehow
  • The "getting around it" part is degrading performance and force a synchronize start and end of a frame, so as to get a measure how close we are to stepping below 60fps.
  • Unfortunately, forcing a synchronize (proverbially gl.finish) doesn't work in every user-agent, and so we'll have to find methods to do that which UAs haven't borked up.
  • If you are on google chrome or IE, insert a gl.readPixels at the start and end of a frame. Don't use gl.finish, it doesn't do anything.
  • If you are on firefox or safari, never use gl.readPixels, it seriously degrades everything. However gl.finish works as intended.
  • Even if we find a solution to consistently across browsers synchronize, it's going to cost us considerable performance. However if given a choice to ridiculously undershoot hardware capabilities (by a factor of say 10000%) in order not to fall below 60fps, or sacrifice ~30% of performance to get a smooth/jitter-free application, or live with ridiculously low framerates and lots of jittering for a sizable percentage of our users, it's not really that much of a contest.
Chrome on windows

Here is where we want to be (ideally). This is a rising JS load test (no webgl) in chrome which nicely shows how well behaved this can be (and what we want to get out of UAs).

Inline image 1

Of course if we toggle to a WebGL load test without any synchronization it looks like this, no indication whatsoever when we're going to drive into a wall.

Inline image 2

Unfortunately, the same is true in chrome when calling gl.finish as well:

Inline image 3

I have tried various other methods (flush, texImage2D, bufferData) and they don't have any appreciatable effect. The only two that do have an effect is readPixels and getError. Get error is not very helpful however.

Inline image 4

So the last command to synchronize things that can work is readPixels, and low and behold, it does work as intended. However this costs us roughly 30% of performance.

Inline image 7

Internet Explorer

Internet explorer doesn't implement even frame division stepping. So at a rising load and no finish no attempt at FPS stepping is evident (other than the 60fps clamping).

Inline image 8

And like in Chrome, gl.finish doesn't seem to do a whole lot (though it does a little more than in Chrome).

Inline image 9

Also like in Chrome, gl.readPixels is about the only solution left:

Inline image 10

Firefox on windows

Firefox also doesn't implement even frame division stepping. And like IE, after the 60fps clamping, interframe times just keep rising. Unlike chrome, firefox seems to spend a considerable amount of time in JS for a few simple loops.
Inline image 11

Here however readPixels seriously mucks things up.

Inline image 12

Luckily, gl.finish is much better behaved:

Inline image 13


I have run these tests on Linux so far also comparing UAs, and have arrived at similar results. It's possible this is different on OSX, and it might also depend on the GPU.