Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

requestAnimationFrame called right before the end of the frame?

I've been experimenting with jank-free rendering of complex scenes on HTML5 canvas. The idea is to split rendering into multiple batches with each batch taking a maximum of, say 12 ms, so that the concurrently running animations (very cheap to execute) are not interrupted.

Conceptually, batch-rendering is implemented like this:

function draw(ctx) {
  var deadline = window.performance.now() + 12; // inaccurate, but enough for the example
  var i = 0;
  requestAnimationFrame(function drawWithDeadline() {
    for (; i < itemsToRender.length; i++) {
      if (window.performance.now() >= deadline) {
        requestAnimationFrame(drawWithDeadline);
        return; 
      }

      var item = itemsToDraw[i];
      // Draw item
    } 
  }); 
}

The complete code is in this JSFiddle: https://jsfiddle.net/fkfnjrc2/5/. The code does the following things:

  • On each frame, modify the CSS transform property of the canvas (which is an example of the concurrently-running fast-to-execute animation).
  • Once in a while, initiate re-rendering of the canvas in the batched fashion as shown above.

Unfortunately, I'm seeing horrible janks exactly at the times when canvas contents is re-rendered. What I don't seem to be able to explain is what the Chrome Developer Tools timeline looks like:

Janks in the Chrome Developer Tools timeline view

The dropped frames seem to be caused by the fact that the requestAnimationFrame is not called right at the start of the frame, but towards the end of the ideal 16ms period. If the callback started right after the previous frame completed rendering, the code would most likely complete in time.

Rendering to an off-screen canvas (https://jsfiddle.net/fkfnjrc2/6/) and then copying the complete image to the screen canvas helps a little, but the janks are still there with exactly the same characteristics (delayed execution of rAF callback).

What is wrong with that code? Or maybe something's wrong with my browser / machine? I'm seeing the same behaviour on Chrome (49.0.2623.112) on Windows 10 and Mac OS.

like image 325
Stanislaw Osinski Avatar asked Nov 08 '22 16:11

Stanislaw Osinski


1 Answers

The issues seem to be caused by Chrome's specific requestAnimationFrame callback scheduling. I've filed a bug to track this, it contains some simpler reproduction code examples.

like image 58
Stanislaw Osinski Avatar answered Nov 15 '22 11:11

Stanislaw Osinski