skia2/tools/perf-canvaskit-puppeteer/skottie-frames.html
Kevin Lubick 8fd0ccfc9f [skottie] Update lotties_with_assets to include all lotties from lottie-samples
The make_lotties_with_assets is a handy tool to take a
directory of lottie files and move them into their own
folders. This will make it easier to add assets (e.g. fonts,
images) if we want to get more accurate benchmarks.

This also makes the test not stop on the first failure, but complete
all of them, so we can see more easily if multiple things have broken.

Change-Id: Idb2ece71376a11e7524cd513a2798884a44bb59f
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/421927
Reviewed-by: Florin Malita <fmalita@google.com>
2021-06-28 14:59:24 +00:00

172 lines
5.6 KiB
HTML

<!-- This benchmark aims to accurately measure the time it takes for Skottie to load the JSON and
turn it into an animation, as well as the times for the first hundred frames (and, as a subcomponent
of that, the seek times of the first hundred frames). This is set to mimic how a real-world user
would display the animation (e.g. using clock time to determine where to seek, not frame numbers).
-->
<!DOCTYPE html>
<html>
<head>
<title>Skottie-WASM Perf</title>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="/static/canvaskit.js" type="text/javascript" charset="utf-8"></script>
<script src="/static/benchmark.js" type="text/javascript" charset="utf-8"></script>
<style type="text/css" media="screen">
body {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<main>
<button id="start_bench">Start Benchmark</button>
<br>
<canvas id=anim width=1000 height=1000 style="height: 1000px; width: 1000px;"></canvas>
</main>
<script type="text/javascript" charset="utf-8">
const WIDTH = 1000;
const HEIGHT = 1000;
const WARM_UP_FRAMES = 0; // No warmup, so that the jank of initial frames gets measured.
// We sample MAX_FRAMES or until MAX_SAMPLE_SECONDS has elapsed.
const MAX_FRAMES = 600; // ~10s at 60fps
const MAX_SAMPLE_MS = 50 * 1000; // in case something takes a while, stop after 50 seconds.
const LOTTIE_JSON_PATH = '/static/lottie.json';
const ASSETS_PATH = '/static/assets/';
(function() {
const loadKit = CanvasKitInit({
locateFile: (file) => '/static/' + file,
});
const loadLottie = fetch(LOTTIE_JSON_PATH).then((resp) => {
return resp.text();
});
const loadFontsAndAssets = loadLottie.then((jsonStr) => {
const lottie = JSON.parse(jsonStr);
const promises = [];
promises.push(...loadFonts(lottie.fonts));
promises.push(...loadAssets(lottie.assets));
return Promise.all(promises);
});
Promise.all([loadKit, loadLottie, loadFontsAndAssets]).then((values) => {
const [CanvasKit, json, externalAssets] = values;
console.log(externalAssets);
const assets = {};
for (const asset of externalAssets) {
if (asset) {
assets[asset.name] = asset.bytes;
}
}
const loadStart = performance.now();
const animation = CanvasKit.MakeManagedAnimation(json, assets);
const loadTime = performance.now() - loadStart;
window._perfData = {
json_load_ms: loadTime,
};
const duration = animation.duration() * 1000;
const bounds = CanvasKit.LTRBRect(0, 0, WIDTH, HEIGHT);
const urlSearchParams = new URLSearchParams(window.location.search);
let glversion = 2;
if (urlSearchParams.has('webgl1')) {
glversion = 1;
}
const surface = getSurface(CanvasKit, glversion);
if (!surface) {
console.error('Could not make surface', window._error);
return;
}
const canvas = surface.getCanvas();
document.getElementById('start_bench').addEventListener('click', async () => {
const startTime = Date.now();
const damageRect = Float32Array.of(0, 0, 0, 0);
function draw() {
const seek = ((Date.now() - startTime) / duration) % 1.0;
const damage = animation.seek(seek, damageRect);
if (damage[2] > damage[0] && damage[3] > damage[1]) {
animation.render(canvas, bounds);
}
}
startTimingFrames(draw, surface, WARM_UP_FRAMES, MAX_FRAMES, MAX_SAMPLE_MS).then((results) => {
Object.assign(window._perfData, results);
window._perfDone = true;
}).catch((error) => {
window._error = error;
});
});
console.log('Perf is ready');
window._perfReady = true;
});
})();
function loadFonts(fonts) {
const promises = [];
if (!fonts || !fonts.list) {
return promises;
}
for (const font of fonts.list) {
if (font.fName) {
promises.push(fetch(`${ASSETS_PATH}/${font.fName}.ttf`).then((resp) => {
// fetch does not reject on 404
if (!resp.ok) {
console.error(`Could not load ${font.fName}.ttf: status ${resp.status}`);
return null;
}
return resp.arrayBuffer().then((buffer) => {
return {
'name': font.fName,
'bytes': buffer
};
});
})
);
}
}
return promises;
}
function loadAssets(assets) {
const promises = [];
if (!assets) {
return [];
}
for (const asset of assets) {
// asset.p is the filename, if it's an image.
// Don't try to load inline/dataURI images.
const should_load = asset.p && asset.p.startsWith && !asset.p.startsWith('data:');
if (should_load) {
promises.push(fetch(`${ASSETS_PATH}/${asset.p}`)
.then((resp) => {
// fetch does not reject on 404
if (!resp.ok) {
console.error(`Could not load ${asset.p}: status ${resp.status}`);
return null;
}
return resp.arrayBuffer().then((buffer) => {
return {
'name': asset.p,
'bytes': buffer
};
});
})
);
}
}
return promises;
}
</script>
</body>
</html>