2020-07-07 21:13:31 +00:00
|
|
|
// Shared benchmarking functions such as surface creation, measurement, publishing to perf.skia.org
|
|
|
|
|
2020-07-17 19:20:44 +00:00
|
|
|
function getSurface(CanvasKit, webglversion) {
|
2020-07-07 21:13:31 +00:00
|
|
|
let surface;
|
|
|
|
if (window.location.hash.indexOf('gpu') !== -1) {
|
2020-07-17 19:20:44 +00:00
|
|
|
surface = CanvasKit.MakeWebGLCanvasSurface('anim', null /* colorspace */, {'majorVersion': webglversion});
|
2020-07-07 21:13:31 +00:00
|
|
|
if (!surface) {
|
|
|
|
window._error = 'Could not make GPU surface';
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
let c = document.getElementById('anim');
|
|
|
|
// If CanvasKit was unable to instantiate a WebGL context, it will fallback
|
|
|
|
// to CPU and add a ck-replaced class to the canvas element.
|
|
|
|
if (c.classList.contains('ck-replaced')) {
|
|
|
|
window._error = 'fell back to CPU';
|
|
|
|
return null;
|
|
|
|
}
|
2020-11-12 14:11:47 +00:00
|
|
|
if (webglversion !== surface.openGLversion) {
|
2020-07-17 19:20:44 +00:00
|
|
|
window._error = 'Want WebGL version '+webglversion+' but got '+surface.openGLversion;
|
|
|
|
return null;
|
|
|
|
}
|
2020-07-07 21:13:31 +00:00
|
|
|
} else {
|
|
|
|
surface = CanvasKit.MakeSWCanvasSurface('anim');
|
|
|
|
if (!surface) {
|
|
|
|
window._error = 'Could not make CPU surface';
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return surface;
|
|
|
|
}
|
|
|
|
|
2020-07-29 15:01:55 +00:00
|
|
|
// Time the drawing and flushing of a frame drawing function on a given surface.
|
2020-07-07 21:13:31 +00:00
|
|
|
// drawFn is expected to be a zero arg function making draw calls to a canvas
|
|
|
|
// warmupFrames - Run this number of frames before starting to measure things.
|
|
|
|
// This allows us to make sure the noise from the first few renders (e.g shader
|
|
|
|
// compilation, caches) is removed from the data we capture.
|
|
|
|
// Stops after timeoutMillis if provided
|
2020-07-29 15:01:55 +00:00
|
|
|
// Teturns a promise that resolves with the dict of measurements.
|
2020-07-07 21:13:31 +00:00
|
|
|
function startTimingFrames(drawFn, surface, warmupFrames, maxFrames, timeoutMillis) {
|
2020-07-29 15:01:55 +00:00
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
const totalFrame = new Float32Array(maxFrames);
|
|
|
|
const withFlush = new Float32Array(maxFrames);
|
|
|
|
const withoutFlush = new Float32Array(maxFrames);
|
|
|
|
let warmUp = warmupFrames > 0;
|
|
|
|
let idx = -1;
|
|
|
|
let previousFrame;
|
2020-07-07 21:13:31 +00:00
|
|
|
|
2020-07-29 15:01:55 +00:00
|
|
|
function drawFrame() {
|
|
|
|
const start = performance.now();
|
|
|
|
drawFn();
|
|
|
|
const afterDraw = performance.now();
|
|
|
|
surface.flush();
|
|
|
|
const end = performance.now();
|
2020-07-07 21:13:31 +00:00
|
|
|
|
2020-07-29 15:01:55 +00:00
|
|
|
if (warmUp) {
|
|
|
|
idx++;
|
|
|
|
if (idx >= warmupFrames) {
|
|
|
|
idx = -1;
|
|
|
|
warmUp = false;
|
|
|
|
}
|
|
|
|
window.requestAnimationFrame(drawFrame);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (idx >= 0) {
|
|
|
|
// Fill out total time the previous frame took to draw.
|
|
|
|
totalFrame[idx] = start - previousFrame;
|
|
|
|
}
|
|
|
|
previousFrame = start;
|
2020-07-07 21:13:31 +00:00
|
|
|
idx++;
|
2020-07-29 15:01:55 +00:00
|
|
|
// If we have maxed out the frames we are measuring or have completed the animation,
|
|
|
|
// we stop benchmarking.
|
|
|
|
if (!window._perfData) {
|
|
|
|
window._perfData = {};
|
|
|
|
}
|
|
|
|
if (idx >= withFlush.length) {
|
|
|
|
resolve({
|
2020-08-10 14:49:02 +00:00
|
|
|
// The total time elapsed between the same point during the drawing of each frame.
|
|
|
|
// This is the most relevant measurement for normal drawing tests.
|
2020-07-29 15:01:55 +00:00
|
|
|
'total_frame_ms': Array.from(totalFrame).slice(0, idx),
|
2020-08-10 14:49:02 +00:00
|
|
|
// The time taken to run the code under test and call surface.flush()
|
2020-07-29 15:01:55 +00:00
|
|
|
'with_flush_ms': Array.from(withFlush).slice(0, idx),
|
2020-08-10 14:49:02 +00:00
|
|
|
// The time taken to run the code under test
|
|
|
|
// This is the most relevant measurement for non-drawing tests such as matrix inversion.
|
2020-07-29 15:01:55 +00:00
|
|
|
'without_flush_ms': Array.from(withoutFlush).slice(0, idx),
|
|
|
|
});
|
|
|
|
return;
|
2020-07-07 21:13:31 +00:00
|
|
|
}
|
|
|
|
|
2020-07-29 15:01:55 +00:00
|
|
|
// We can fill out this frame's intermediate steps.
|
|
|
|
withFlush[idx] = end - start;
|
|
|
|
withoutFlush[idx] = afterDraw - start;
|
2020-07-16 17:25:01 +00:00
|
|
|
|
2020-07-29 15:01:55 +00:00
|
|
|
if (timeoutMillis && ((beginTest + timeoutMillis) < performance.now())) {
|
2020-11-12 14:11:47 +00:00
|
|
|
console.log(`test aborted due to timeout after ${idx} frames`);
|
|
|
|
reject(`test aborted due to timeout after ${idx} frames`);
|
2020-07-29 15:01:55 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
window.requestAnimationFrame(drawFrame);
|
2020-07-07 21:13:31 +00:00
|
|
|
}
|
2020-07-29 15:01:55 +00:00
|
|
|
const beginTest = performance.now();
|
2020-07-07 21:13:31 +00:00
|
|
|
window.requestAnimationFrame(drawFrame);
|
2020-07-29 15:01:55 +00:00
|
|
|
}); // new promise
|
|
|
|
}
|