2021-09-27 19:58:13 +02:00
|
|
|
import * as tf from '../../dist/tfjs.esm.js';
|
|
|
|
import * as image from '../image/image';
|
2021-09-12 18:42:17 +02:00
|
|
|
|
2021-10-21 16:26:44 +02:00
|
|
|
/** Env class that holds detected capabilities */
|
|
|
|
export class Env {
|
2021-10-10 23:52:43 +02:00
|
|
|
/** Running in Browser */
|
2021-10-21 16:26:44 +02:00
|
|
|
browser: boolean;
|
2021-10-10 23:52:43 +02:00
|
|
|
/** Running in NodeJS */
|
2021-10-21 16:26:44 +02:00
|
|
|
node: boolean;
|
2021-10-10 23:52:43 +02:00
|
|
|
/** Running in WebWorker thread */
|
2021-10-21 16:26:44 +02:00
|
|
|
worker: boolean;
|
2021-10-10 23:52:43 +02:00
|
|
|
/** Detected platform */
|
2021-10-21 16:26:44 +02:00
|
|
|
platform: string = '';
|
2021-10-10 23:52:43 +02:00
|
|
|
/** Detected agent */
|
2021-10-21 16:26:44 +02:00
|
|
|
agent: string = '';
|
2021-10-10 23:52:43 +02:00
|
|
|
/** List of supported backends */
|
2021-10-21 16:26:44 +02:00
|
|
|
backends: string[] = [];
|
2021-10-10 23:52:43 +02:00
|
|
|
/** Has any work been performed so far */
|
2021-10-21 16:26:44 +02:00
|
|
|
initial: boolean;
|
2021-10-10 23:52:43 +02:00
|
|
|
/** Are image filters supported? */
|
2021-10-21 16:26:44 +02:00
|
|
|
filter: boolean | undefined;
|
2021-10-10 23:52:43 +02:00
|
|
|
/** TFJS instance details */
|
2021-09-12 18:42:17 +02:00
|
|
|
tfjs: {
|
|
|
|
version: undefined | string,
|
2021-10-21 16:26:44 +02:00
|
|
|
};
|
2021-10-10 23:52:43 +02:00
|
|
|
/** Is offscreenCanvas supported? */
|
2021-10-21 16:26:44 +02:00
|
|
|
offscreen: undefined | boolean;
|
2021-10-23 15:38:52 +02:00
|
|
|
/** Are performance counter instant values or additive */
|
|
|
|
perfadd: boolean = false;
|
2021-10-10 23:52:43 +02:00
|
|
|
/** WASM detected capabilities */
|
2021-09-12 18:42:17 +02:00
|
|
|
wasm: {
|
|
|
|
supported: undefined | boolean,
|
2021-09-14 05:24:04 +02:00
|
|
|
backend: undefined | boolean,
|
2021-09-12 18:42:17 +02:00
|
|
|
simd: undefined | boolean,
|
|
|
|
multithread: undefined | boolean,
|
2021-10-21 16:26:44 +02:00
|
|
|
} = {
|
|
|
|
supported: undefined,
|
|
|
|
backend: undefined,
|
|
|
|
simd: undefined,
|
|
|
|
multithread: undefined,
|
|
|
|
};
|
2021-10-10 23:52:43 +02:00
|
|
|
/** WebGL detected capabilities */
|
2021-09-12 18:42:17 +02:00
|
|
|
webgl: {
|
|
|
|
supported: undefined | boolean,
|
2021-09-14 05:24:04 +02:00
|
|
|
backend: undefined | boolean,
|
2021-09-12 18:42:17 +02:00
|
|
|
version: undefined | string,
|
|
|
|
renderer: undefined | string,
|
2021-10-21 16:26:44 +02:00
|
|
|
} = {
|
|
|
|
supported: undefined,
|
|
|
|
backend: undefined,
|
|
|
|
version: undefined,
|
|
|
|
renderer: undefined,
|
|
|
|
};
|
2021-10-10 23:52:43 +02:00
|
|
|
/** WebGPU detected capabilities */
|
2021-09-12 18:42:17 +02:00
|
|
|
webgpu: {
|
|
|
|
supported: undefined | boolean,
|
2021-09-14 05:24:04 +02:00
|
|
|
backend: undefined | boolean,
|
2021-09-12 18:42:17 +02:00
|
|
|
adapter: undefined | string,
|
2021-10-21 16:26:44 +02:00
|
|
|
} = {
|
|
|
|
supported: undefined,
|
|
|
|
backend: undefined,
|
|
|
|
adapter: undefined,
|
|
|
|
};
|
|
|
|
/** CPU info */
|
|
|
|
cpu: {
|
|
|
|
model: undefined | string,
|
|
|
|
flags: string[],
|
|
|
|
} = {
|
|
|
|
model: undefined,
|
|
|
|
flags: [],
|
|
|
|
};
|
2021-10-10 23:52:43 +02:00
|
|
|
/** List of supported kernels for current backend */
|
2021-10-21 16:26:44 +02:00
|
|
|
kernels: string[] = [];
|
2021-10-10 23:52:43 +02:00
|
|
|
/** MonkeyPatch for Canvas */
|
2021-10-21 16:26:44 +02:00
|
|
|
Canvas: undefined;
|
2021-10-10 23:52:43 +02:00
|
|
|
/** MonkeyPatch for Image */
|
2021-10-21 16:26:44 +02:00
|
|
|
Image: undefined;
|
2021-10-10 23:52:43 +02:00
|
|
|
/** MonkeyPatch for ImageData */
|
2021-10-21 16:26:44 +02:00
|
|
|
ImageData: undefined;
|
2021-09-12 18:42:17 +02:00
|
|
|
|
2021-10-21 16:26:44 +02:00
|
|
|
constructor() {
|
|
|
|
this.browser = typeof navigator !== 'undefined';
|
|
|
|
this.node = typeof process !== 'undefined';
|
|
|
|
this.tfjs = { version: tf.version_core };
|
|
|
|
this.offscreen = typeof OffscreenCanvas !== 'undefined';
|
|
|
|
this.initial = true;
|
|
|
|
// @ts-ignore WorkerGlobalScope evaluated in browser only
|
|
|
|
this.worker = this.browser && this.offscreen ? (typeof WorkerGlobalScope !== 'undefined') : undefined;
|
|
|
|
if (typeof navigator !== 'undefined') {
|
|
|
|
const raw = navigator.userAgent.match(/\(([^()]+)\)/g);
|
|
|
|
if (raw && raw[0]) {
|
|
|
|
const platformMatch = raw[0].match(/\(([^()]+)\)/g);
|
|
|
|
this.platform = (platformMatch && platformMatch[0]) ? platformMatch[0].replace(/\(|\)/g, '') : '';
|
|
|
|
this.agent = navigator.userAgent.replace(raw[0], '');
|
|
|
|
if (this.platform[1]) this.agent = this.agent.replace(raw[1], '');
|
|
|
|
this.agent = this.agent.replace(/ /g, ' ');
|
|
|
|
// chrome offscreencanvas gpu memory leak
|
|
|
|
/*
|
|
|
|
const isChrome = env.agent.match(/Chrome\/.[0-9]/g);
|
|
|
|
const verChrome = isChrome && isChrome[0] ? isChrome[0].split('/')[1] : 0;
|
|
|
|
if (verChrome > 92 && verChrome < 96) {
|
|
|
|
log('disabling offscreenCanvas due to browser error:', isChrome ? isChrome[0] : 'unknown');
|
|
|
|
this.offscreen = false;
|
2021-09-12 18:42:17 +02:00
|
|
|
}
|
2021-10-21 16:26:44 +02:00
|
|
|
*/
|
2021-09-12 18:42:17 +02:00
|
|
|
}
|
2021-10-21 16:26:44 +02:00
|
|
|
} else if (typeof process !== 'undefined') {
|
|
|
|
this.platform = `${process.platform} ${process.arch}`;
|
|
|
|
this.agent = `NodeJS ${process.version}`;
|
2021-09-14 05:24:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-11-17 21:45:49 +01:00
|
|
|
/** update backend information */
|
2021-10-21 16:26:44 +02:00
|
|
|
async updateBackend() {
|
|
|
|
// analyze backends
|
|
|
|
this.backends = Object.keys(tf.engine().registryFactory);
|
|
|
|
this.wasm.supported = typeof WebAssembly !== 'undefined';
|
|
|
|
this.wasm.backend = this.backends.includes('wasm');
|
|
|
|
if (this.wasm.supported && this.wasm.backend && tf.getBackend() === 'wasm') {
|
|
|
|
this.wasm.simd = await tf.env().getAsync('WASM_HAS_SIMD_SUPPORT');
|
|
|
|
this.wasm.multithread = await tf.env().getAsync('WASM_HAS_MULTITHREAD_SUPPORT');
|
|
|
|
}
|
|
|
|
const c = image.canvas(100, 100);
|
|
|
|
const ctx = c ? c.getContext('webgl2') : undefined; // causes too many gl contexts
|
|
|
|
// const ctx = typeof tf.backend().getGPGPUContext !== undefined ? tf.backend().getGPGPUContext : null;
|
|
|
|
this.webgl.supported = typeof ctx !== 'undefined';
|
|
|
|
this.webgl.backend = this.backends.includes('webgl');
|
|
|
|
if (this.webgl.supported && this.webgl.backend && (tf.getBackend() === 'webgl' || tf.getBackend() === 'humangl')) {
|
|
|
|
// @ts-ignore getGPGPUContext only exists on WebGL backend
|
|
|
|
const gl = tf.backend().gpgpu !== 'undefined' ? await tf.backend().getGPGPUContext().gl : null;
|
|
|
|
if (gl) {
|
|
|
|
this.webgl.version = gl.getParameter(gl.VERSION);
|
|
|
|
this.webgl.renderer = gl.getParameter(gl.RENDERER);
|
2021-10-06 17:30:34 +02:00
|
|
|
}
|
2021-09-12 18:42:17 +02:00
|
|
|
}
|
2021-10-21 16:26:44 +02:00
|
|
|
this.webgpu.supported = this.browser && typeof navigator['gpu'] !== 'undefined';
|
|
|
|
this.webgpu.backend = this.backends.includes('webgpu');
|
2021-11-14 17:22:52 +01:00
|
|
|
try {
|
|
|
|
if (this.webgpu.supported) this.webgpu.adapter = (await navigator['gpu'].requestAdapter()).name;
|
|
|
|
// enumerate kernels
|
|
|
|
this.kernels = tf.getKernelsForBackend(tf.getBackend()).map((kernel) => kernel.kernelName.toLowerCase());
|
|
|
|
} catch {
|
|
|
|
this.webgpu.supported = false;
|
|
|
|
}
|
2021-09-12 18:42:17 +02:00
|
|
|
}
|
|
|
|
|
2021-11-17 21:45:49 +01:00
|
|
|
/** update cpu information */
|
2021-10-21 16:26:44 +02:00
|
|
|
async updateCPU() {
|
|
|
|
const cpu = { model: '', flags: [] };
|
2021-11-04 11:34:13 +01:00
|
|
|
if (this.node && this.platform.startsWith('linux')) {
|
2021-10-21 16:26:44 +02:00
|
|
|
// eslint-disable-next-line global-require
|
2021-11-17 22:50:21 +01:00
|
|
|
/*
|
2021-10-21 16:26:44 +02:00
|
|
|
const fs = require('fs');
|
|
|
|
try {
|
|
|
|
const data = fs.readFileSync('/proc/cpuinfo').toString();
|
|
|
|
for (const line of data.split('\n')) {
|
|
|
|
if (line.startsWith('model name')) {
|
|
|
|
cpu.model = line.match(/:(.*)/g)[0].replace(':', '').trim();
|
|
|
|
}
|
|
|
|
if (line.startsWith('flags')) {
|
|
|
|
cpu.flags = line.match(/:(.*)/g)[0].replace(':', '').trim().split(' ').sort();
|
|
|
|
}
|
|
|
|
}
|
2021-11-17 22:50:21 +01:00
|
|
|
} catch { }
|
|
|
|
*/
|
2021-10-21 16:26:44 +02:00
|
|
|
}
|
|
|
|
if (!this['cpu']) Object.defineProperty(this, 'cpu', { value: cpu });
|
|
|
|
else this['cpu'] = cpu;
|
|
|
|
}
|
2021-09-12 18:42:17 +02:00
|
|
|
}
|
2021-09-20 23:17:13 +02:00
|
|
|
|
2021-10-21 16:26:44 +02:00
|
|
|
export const env = new Env();
|