xref: /aosp_15_r20/external/skia/tools/perf-canvaskit-puppeteer/benchmark.js (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker// Shared benchmarking functions such as surface creation, measurement, publishing to perf.skia.org
2*c8dee2aaSAndroid Build Coastguard Worker
3*c8dee2aaSAndroid Build Coastguard Workerfunction getSurface(CanvasKit, webglversion) {
4*c8dee2aaSAndroid Build Coastguard Worker  let surface;
5*c8dee2aaSAndroid Build Coastguard Worker  if (window.location.hash.indexOf('gpu') !== -1) {
6*c8dee2aaSAndroid Build Coastguard Worker    surface = CanvasKit.MakeWebGLCanvasSurface('anim', null /* colorspace */, {'majorVersion': webglversion});
7*c8dee2aaSAndroid Build Coastguard Worker    if (!surface) {
8*c8dee2aaSAndroid Build Coastguard Worker      window._error = 'Could not make GPU surface';
9*c8dee2aaSAndroid Build Coastguard Worker      return null;
10*c8dee2aaSAndroid Build Coastguard Worker    }
11*c8dee2aaSAndroid Build Coastguard Worker    let c = document.getElementById('anim');
12*c8dee2aaSAndroid Build Coastguard Worker    // If CanvasKit was unable to instantiate a WebGL context, it will fallback
13*c8dee2aaSAndroid Build Coastguard Worker    // to CPU and add a ck-replaced class to the canvas element.
14*c8dee2aaSAndroid Build Coastguard Worker    if (c.classList.contains('ck-replaced')) {
15*c8dee2aaSAndroid Build Coastguard Worker      window._error = 'fell back to CPU';
16*c8dee2aaSAndroid Build Coastguard Worker      return null;
17*c8dee2aaSAndroid Build Coastguard Worker    }
18*c8dee2aaSAndroid Build Coastguard Worker  } else {
19*c8dee2aaSAndroid Build Coastguard Worker    surface = CanvasKit.MakeSWCanvasSurface('anim');
20*c8dee2aaSAndroid Build Coastguard Worker    if (!surface) {
21*c8dee2aaSAndroid Build Coastguard Worker      window._error = 'Could not make CPU surface';
22*c8dee2aaSAndroid Build Coastguard Worker      return null;
23*c8dee2aaSAndroid Build Coastguard Worker    }
24*c8dee2aaSAndroid Build Coastguard Worker  }
25*c8dee2aaSAndroid Build Coastguard Worker  return surface;
26*c8dee2aaSAndroid Build Coastguard Worker}
27*c8dee2aaSAndroid Build Coastguard Worker
28*c8dee2aaSAndroid Build Coastguard Worker// Time the drawing and flushing of a frame drawing function on a given surface.
29*c8dee2aaSAndroid Build Coastguard Worker// drawFn is expected to be a zero arg function making draw calls to a canvas
30*c8dee2aaSAndroid Build Coastguard Worker// warmupFrames - Run this number of frames before starting to measure things.
31*c8dee2aaSAndroid Build Coastguard Worker//   This allows us to make sure the noise from the first few renders (e.g shader
32*c8dee2aaSAndroid Build Coastguard Worker//   compilation, caches) is removed from the data we capture.
33*c8dee2aaSAndroid Build Coastguard Worker// Stops after timeoutMillis if provided
34*c8dee2aaSAndroid Build Coastguard Worker// Teturns a promise that resolves with the dict of measurements.
35*c8dee2aaSAndroid Build Coastguard Workerfunction startTimingFrames(drawFn, surface, warmupFrames, maxFrames, timeoutMillis) {
36*c8dee2aaSAndroid Build Coastguard Worker  return new Promise((resolve, reject) => {
37*c8dee2aaSAndroid Build Coastguard Worker    const totalFrame = new Float32Array(maxFrames);
38*c8dee2aaSAndroid Build Coastguard Worker    const withFlush = new Float32Array(maxFrames);
39*c8dee2aaSAndroid Build Coastguard Worker    const withoutFlush = new Float32Array(maxFrames);
40*c8dee2aaSAndroid Build Coastguard Worker    let warmUp = warmupFrames > 0;
41*c8dee2aaSAndroid Build Coastguard Worker    let idx = -1;
42*c8dee2aaSAndroid Build Coastguard Worker    let previousFrame;
43*c8dee2aaSAndroid Build Coastguard Worker
44*c8dee2aaSAndroid Build Coastguard Worker    function drawFrame() {
45*c8dee2aaSAndroid Build Coastguard Worker      let start, afterDraw, end;
46*c8dee2aaSAndroid Build Coastguard Worker      try {
47*c8dee2aaSAndroid Build Coastguard Worker        start = performance.now();
48*c8dee2aaSAndroid Build Coastguard Worker        drawFn();
49*c8dee2aaSAndroid Build Coastguard Worker        afterDraw = performance.now();
50*c8dee2aaSAndroid Build Coastguard Worker        surface.flush();
51*c8dee2aaSAndroid Build Coastguard Worker        end = performance.now();
52*c8dee2aaSAndroid Build Coastguard Worker      } catch (e) {
53*c8dee2aaSAndroid Build Coastguard Worker        console.error(e);
54*c8dee2aaSAndroid Build Coastguard Worker        window._error = e.stack || e.toString();
55*c8dee2aaSAndroid Build Coastguard Worker        return;
56*c8dee2aaSAndroid Build Coastguard Worker      }
57*c8dee2aaSAndroid Build Coastguard Worker
58*c8dee2aaSAndroid Build Coastguard Worker      if (warmUp) {
59*c8dee2aaSAndroid Build Coastguard Worker        idx++;
60*c8dee2aaSAndroid Build Coastguard Worker        if (idx >= warmupFrames) {
61*c8dee2aaSAndroid Build Coastguard Worker          idx = -1;
62*c8dee2aaSAndroid Build Coastguard Worker          warmUp = false;
63*c8dee2aaSAndroid Build Coastguard Worker        }
64*c8dee2aaSAndroid Build Coastguard Worker        window.requestAnimationFrame(drawFrame);
65*c8dee2aaSAndroid Build Coastguard Worker        return;
66*c8dee2aaSAndroid Build Coastguard Worker      }
67*c8dee2aaSAndroid Build Coastguard Worker      if (idx >= 0) {
68*c8dee2aaSAndroid Build Coastguard Worker        // Fill out total time the previous frame took to draw.
69*c8dee2aaSAndroid Build Coastguard Worker        totalFrame[idx] = start - previousFrame;
70*c8dee2aaSAndroid Build Coastguard Worker      }
71*c8dee2aaSAndroid Build Coastguard Worker      previousFrame = start;
72*c8dee2aaSAndroid Build Coastguard Worker      idx++;
73*c8dee2aaSAndroid Build Coastguard Worker      // If we have maxed out the frames we are measuring or have completed the animation,
74*c8dee2aaSAndroid Build Coastguard Worker      // we stop benchmarking.
75*c8dee2aaSAndroid Build Coastguard Worker      if (!window._perfData) {
76*c8dee2aaSAndroid Build Coastguard Worker        window._perfData = {};
77*c8dee2aaSAndroid Build Coastguard Worker      }
78*c8dee2aaSAndroid Build Coastguard Worker      if (idx >= withFlush.length) {
79*c8dee2aaSAndroid Build Coastguard Worker        resolve({
80*c8dee2aaSAndroid Build Coastguard Worker          // The total time elapsed between the same point during the drawing of each frame.
81*c8dee2aaSAndroid Build Coastguard Worker          // This is the most relevant measurement for normal drawing tests.
82*c8dee2aaSAndroid Build Coastguard Worker          'total_frame_ms': Array.from(totalFrame).slice(0, idx),
83*c8dee2aaSAndroid Build Coastguard Worker          // The time taken to run the code under test and call surface.flush()
84*c8dee2aaSAndroid Build Coastguard Worker          'with_flush_ms': Array.from(withFlush).slice(0, idx),
85*c8dee2aaSAndroid Build Coastguard Worker          // The time taken to run the code under test
86*c8dee2aaSAndroid Build Coastguard Worker          // This is the most relevant measurement for non-drawing tests such as matrix inversion.
87*c8dee2aaSAndroid Build Coastguard Worker          'without_flush_ms': Array.from(withoutFlush).slice(0, idx),
88*c8dee2aaSAndroid Build Coastguard Worker        });
89*c8dee2aaSAndroid Build Coastguard Worker        return;
90*c8dee2aaSAndroid Build Coastguard Worker      }
91*c8dee2aaSAndroid Build Coastguard Worker
92*c8dee2aaSAndroid Build Coastguard Worker      // We can fill out this frame's intermediate steps.
93*c8dee2aaSAndroid Build Coastguard Worker      withFlush[idx] = end - start;
94*c8dee2aaSAndroid Build Coastguard Worker      withoutFlush[idx] = afterDraw - start;
95*c8dee2aaSAndroid Build Coastguard Worker
96*c8dee2aaSAndroid Build Coastguard Worker      if (timeoutMillis && ((beginTest + timeoutMillis) < performance.now())) {
97*c8dee2aaSAndroid Build Coastguard Worker        console.log(`test aborted due to timeout after ${idx} frames`);
98*c8dee2aaSAndroid Build Coastguard Worker        reject(`test aborted due to timeout after ${idx} frames`);
99*c8dee2aaSAndroid Build Coastguard Worker        return;
100*c8dee2aaSAndroid Build Coastguard Worker      }
101*c8dee2aaSAndroid Build Coastguard Worker      window.requestAnimationFrame(drawFrame);
102*c8dee2aaSAndroid Build Coastguard Worker    }
103*c8dee2aaSAndroid Build Coastguard Worker    const beginTest = performance.now();
104*c8dee2aaSAndroid Build Coastguard Worker    window.requestAnimationFrame(drawFrame);
105*c8dee2aaSAndroid Build Coastguard Worker  }); // new promise
106*c8dee2aaSAndroid Build Coastguard Worker}
107