115 lines
4.1 KiB
HTML
115 lines
4.1 KiB
HTML
<!doctype html>
|
|
<html>
|
|
<head><meta charset="utf-8"><title>W0 GPU bench</title></head>
|
|
<body>
|
|
<pre id="out">running…</pre>
|
|
<script src="/bin/full/canvaskit.js"></script>
|
|
<script>
|
|
(async () => {
|
|
const CanvasKitInit = window.CanvasKitInit;
|
|
|
|
const log = (s) => { document.getElementById('out').textContent += '\n' + s; };
|
|
const results = {};
|
|
|
|
try {
|
|
const CK = await CanvasKitInit({ locateFile: (f) => '/bin/full/' + f });
|
|
|
|
const img = await fetch('/samples/p2.jpg').then((r) => r.arrayBuffer()).then((b) => new Uint8Array(b));
|
|
let t0 = performance.now();
|
|
const src = CK.MakeImageFromEncoded(img);
|
|
log(`decode 12MP: ${(performance.now() - t0).toFixed(0)}ms ${src.width()}x${src.height()}`);
|
|
|
|
const W = src.width();
|
|
const H = src.height();
|
|
const sizes = [
|
|
{ name: '1024', w: 1024, h: Math.round((1024 * H) / W) },
|
|
{ name: '2048', w: 2048, h: Math.round((2048 * H) / W) },
|
|
{ name: 'full', w: W, h: H },
|
|
];
|
|
|
|
const tone = CK.RuntimeEffect.Make(
|
|
'uniform shader src; uniform float a; vec4 main(vec2 p){ vec4 c = src.eval(p); return vec4(c.rgb*(1.0+a), c.a);}'
|
|
);
|
|
const sharpen = CK.RuntimeEffect.Make(
|
|
'uniform shader img; uniform float2 texel; uniform float amount; vec4 main(vec2 p){ vec4 c=img.eval(p); vec4 n=img.eval(p+float2(0.0,-texel.y)); vec4 s=img.eval(p+float2(0.0,texel.y)); vec4 w=img.eval(p+float2(-texel.x,0.0)); vec4 e=img.eval(p+float2(texel.x,0.0)); return vec4(clamp(c.rgb*(1.0+4.0*amount)-amount*(n.rgb+s.rgb+w.rgb+e.rgb),0.0,1.0), c.a);}'
|
|
);
|
|
log('runtime effects: tone=' + !!tone + ' sharpen=' + !!sharpen);
|
|
|
|
for (const s of sizes) {
|
|
log(`\n[webgl canvas ${s.w}x${s.h}]`);
|
|
const canvas = new OffscreenCanvas(s.w, s.h);
|
|
const gl0 = canvas.getContext('webgl2');
|
|
const dbg = gl0 && gl0.getExtension('WEBGL_debug_renderer_info');
|
|
if (dbg) log(' GL: ' + gl0.getParameter(dbg.UNMASKED_RENDERER_WEBGL));
|
|
t0 = performance.now();
|
|
const surface = CK.MakeWebGLCanvasSurface(canvas);
|
|
log(` MakeWebGLCanvasSurface: ${(performance.now() - t0).toFixed(0)}ms ok=${!!surface}`);
|
|
if (!surface) continue;
|
|
const cv = surface.getCanvas();
|
|
results[s.name] = {};
|
|
|
|
const shader = src.makeShaderOptions(CK.TileMode.Clamp, CK.TileMode.Clamp, CK.FilterMode.Linear, CK.MipmapMode.None);
|
|
const toneShader = tone.makeShaderWithChildren([0.2], [shader]);
|
|
|
|
const draw = () => {
|
|
const p = new CK.Paint();
|
|
p.setShader(toneShader);
|
|
cv.drawRect(CK.XYWHRect(0, 0, s.w, s.h), p);
|
|
surface.flush();
|
|
p.delete();
|
|
};
|
|
draw(); // warm-up: shader compile + texture upload
|
|
const measure = (label, fn) => {
|
|
fn();
|
|
const t = performance.now();
|
|
fn();
|
|
const ms = performance.now() - t;
|
|
log(` ${label.padEnd(26)} ${ms.toFixed(0)}ms`);
|
|
results[s.name][label] = ms;
|
|
};
|
|
|
|
measure('tone skSL pass', draw);
|
|
|
|
measure('clarity skSL 5-tap', () => {
|
|
const snap = surface.makeImageSnapshot();
|
|
const child = snap.makeShaderOptions(CK.TileMode.Clamp, CK.TileMode.Clamp, CK.FilterMode.Linear, CK.MipmapMode.None);
|
|
const sh = sharpen.makeShaderWithChildren([0.3, 1, 1], [child]);
|
|
const p = new CK.Paint();
|
|
p.setShader(sh);
|
|
cv.drawRect(CK.XYWHRect(0, 0, s.w, s.h), p);
|
|
surface.flush();
|
|
p.delete(); sh.delete(); child.delete(); snap.delete();
|
|
});
|
|
|
|
measure('blur sigma=40', () => {
|
|
const snap = surface.makeImageSnapshot();
|
|
const p = new CK.Paint();
|
|
p.setImageFilter(CK.ImageFilter.MakeBlur(40, 40, CK.TileMode.Clamp, null));
|
|
cv.clear(CK.Color(0, 0, 0, 0));
|
|
cv.drawImage(snap, 0, 0, p);
|
|
surface.flush();
|
|
p.delete(); snap.delete();
|
|
});
|
|
|
|
let enc = -1;
|
|
measure('jpeg q95 encode', () => {
|
|
const snap = surface.makeImageSnapshot();
|
|
const b = snap.encodeToBytes(CK.ImageFormat.JPEG, 95);
|
|
enc = b ? b.length : -1;
|
|
snap.delete();
|
|
});
|
|
log(' encoded bytes: ' + enc);
|
|
surface.delete();
|
|
}
|
|
window.__results = results;
|
|
log('\nDONE');
|
|
document.title = 'done';
|
|
} catch (e) {
|
|
log('ERROR ' + (e && e.stack ? e.stack : e));
|
|
document.title = 'error';
|
|
}
|
|
})();
|
|
</script>
|
|
</body>
|
|
</html>
|