add webgu checks

pull/193/head
Vladimir Mandic 2021-08-15 08:09:40 -04:00
parent 5022c416be
commit c97eb67c5b
16 changed files with 323 additions and 96 deletions

View File

@ -11,6 +11,8 @@ Repository: **<git+https://github.com/vladmandic/human.git>**
### **HEAD -> main** 2021/08/14 mandic00@live.com
- experimental webgpu support
- add experimental webgu demo
- add backend initialization checks
- complete async work
- list detect cameras

View File

@ -6,40 +6,131 @@
*/
// @ts-nocheck // typescript checks disabled as this is pure javascript
import '../../node_modules/@tensorflow/tfjs-core/dist/tf-core.es2017.js';
import '../../assets/tf-backend-webgpu.es2017.js';
import Human from '../../dist/human.esm.js';
import GLBench from '../helpers/gl-bench.js';
const workerJS = './worker.js';
const backend = 'webgpu';
const config = {
main: { // processes input and runs gesture analysis
warmup: 'none',
backend,
modelBasePath: '../../models/',
async: false,
filter: { enabled: true },
face: { enabled: false },
object: { enabled: false },
gesture: { enabled: true },
hand: { enabled: false },
body: { enabled: false },
segmentation: { enabled: false },
},
face: { // runs all face models
warmup: 'none',
backend,
modelBasePath: '../../models/',
async: false,
filter: { enabled: false },
face: { enabled: true,
detector: { return: false, rotation: false },
mesh: { enabled: true },
iris: { enabled: false },
description: { enabled: true },
emotion: { enabled: false },
},
object: { enabled: false },
gesture: { enabled: false },
hand: { enabled: false },
body: { enabled: false },
segmentation: { enabled: false },
},
body: { // runs body model
warmup: 'none',
backend,
modelBasePath: '../../models/',
async: false,
filter: { enabled: false },
face: { enabled: false },
object: { enabled: false },
gesture: { enabled: false },
hand: { enabled: false },
body: { enabled: true },
segmentation: { enabled: false },
},
hand: { // runs hands model
warmup: 'none',
backend,
modelBasePath: '../../models/',
async: false,
filter: { enabled: false },
face: { enabled: false },
object: { enabled: false },
gesture: { enabled: false },
hand: { enabled: true, rotation: false },
body: { enabled: false },
segmentation: { enabled: false },
},
object: { // runs object model
warmup: 'none',
backend,
modelBasePath: '../../models/',
async: false,
filter: { enabled: false },
face: { enabled: false },
object: { enabled: false },
gesture: { enabled: false },
hand: { enabled: false },
body: { enabled: false },
segmentation: { enabled: false },
},
};
let human;
let canvas;
let video;
let result;
let bench;
const myConfig = {
backend: 'webgl',
async: true,
warmup: 'none',
modelBasePath: '../../models',
cacheSensitivity: 0,
filter: {
enabled: true,
flip: false,
},
face: { enabled: true,
detector: { return: false, rotation: false },
mesh: { enabled: true },
iris: { enabled: false },
description: { enabled: true },
emotion: { enabled: false },
},
object: { enabled: false },
gesture: { enabled: true },
hand: { enabled: true, rotation: false },
body: { enabled: true },
segmentation: { enabled: false },
const busy = {
face: false,
hand: false,
body: false,
object: false,
};
let time = 0;
const workers = {
face: null,
body: null,
hand: null,
object: null,
};
const time = {
main: 0,
draw: 0,
face: '[warmup]',
body: '[warmup]',
hand: '[warmup]',
object: '[warmup]',
};
const start = {
main: 0,
draw: 0,
face: 0,
body: 0,
hand: 0,
object: 0,
};
const result = { // initialize empty result object which will be partially filled with results from each thread
performance: {},
hand: [],
body: [],
face: [],
object: [],
};
function log(...msg) {
const dt = new Date();
@ -49,18 +140,57 @@ function log(...msg) {
}
async function drawResults() {
start.draw = performance.now();
const interpolated = human.next(result);
const ctx = canvas.getContext('2d');
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
await human.draw.all(canvas, interpolated);
document.getElementById('log').innerText = `Human: version ${human.version} | ${Math.trunc(time)} ms | FPS: ${Math.trunc(10000 / time) / 10}`;
time.draw = Math.round(1 + performance.now() - start.draw);
const fps = Math.round(10 * 1000 / time.main) / 10;
const draw = Math.round(10 * 1000 / time.draw) / 10;
document.getElementById('log').innerText = `Human: version ${human.version} | Performance: Main ${time.main}ms Face: ${time.face}ms Body: ${time.body}ms Hand: ${time.hand}ms Object ${time.object}ms | FPS: ${fps} / ${draw}`;
requestAnimationFrame(drawResults);
}
async function receiveMessage(msg) {
result[msg.data.type] = msg.data.result;
busy[msg.data.type] = false;
time[msg.data.type] = Math.round(performance.now() - start[msg.data.type]);
}
async function runDetection() {
const t0 = performance.now();
result = await human.detect(video);
time = performance.now() - t0;
start.main = performance.now();
if (!bench) {
bench = new GLBench(null, { trackGPU: false, chartHz: 20, chartLen: 20 });
bench.begin();
}
const ctx = canvas.getContext('2d');
// const image = await human.image(video);
// ctx.drawImage(image.canvas, 0, 0, canvas.width, canvas.height);
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
if (!busy.face) {
busy.face = true;
start.face = performance.now();
workers.face.postMessage({ image: imageData.data.buffer, width: canvas.width, height: canvas.height, config: config.face, type: 'face' }, [imageData.data.buffer.slice(0)]);
}
if (!busy.body) {
busy.body = true;
start.body = performance.now();
workers.body.postMessage({ image: imageData.data.buffer, width: canvas.width, height: canvas.height, config: config.body, type: 'body' }, [imageData.data.buffer.slice(0)]);
}
if (!busy.hand) {
busy.hand = true;
start.hand = performance.now();
workers.hand.postMessage({ image: imageData.data.buffer, width: canvas.width, height: canvas.height, config: config.hand, type: 'hand' }, [imageData.data.buffer.slice(0)]);
}
if (!busy.object) {
busy.object = true;
start.object = performance.now();
workers.object.postMessage({ image: imageData.data.buffer, width: canvas.width, height: canvas.height, config: config.object, type: 'object' }, [imageData.data.buffer.slice(0)]);
}
time.main = Math.round(performance.now() - start.main);
bench.nextFrame();
requestAnimationFrame(runDetection);
}
@ -80,7 +210,7 @@ async function setupCamera() {
},
};
// enumerate devices for diag purposes
navigator.mediaDevices.enumerateDevices().then((devices) => log('enumerated input devices:', devices));
navigator.mediaDevices.enumerateDevices().then((devices) => log('enumerated devices:', devices));
log('camera constraints', constraints);
try {
stream = await navigator.mediaDevices.getUserMedia(constraints);
@ -109,9 +239,35 @@ async function setupCamera() {
return promise;
}
async function startWorkers() {
if (!workers.face) workers.face = new Worker(workerJS);
if (!workers.body) workers.body = new Worker(workerJS);
if (!workers.hand) workers.hand = new Worker(workerJS);
if (!workers.object) workers.object = new Worker(workerJS);
workers.face.onmessage = receiveMessage;
workers.body.onmessage = receiveMessage;
workers.hand.onmessage = receiveMessage;
workers.object.onmessage = receiveMessage;
}
async function main() {
human = new Human(myConfig);
window.addEventListener('unhandledrejection', (evt) => {
// eslint-disable-next-line no-console
console.error(evt.reason || evt);
document.getElementById('log').innerHTML = evt.reason.message || evt.reason || evt;
status('exception error');
evt.preventDefault();
});
if (typeof Worker === 'undefined' || typeof OffscreenCanvas === 'undefined') {
status('workers are not supported');
return;
}
human = new Human(config.main);
document.getElementById('log').innerText = `Human: version ${human.version}`;
await startWorkers();
await setupCamera();
runDetection();
drawResults();

22
demo/webgpu/worker.js Normal file
View File

@ -0,0 +1,22 @@
// load Human using IIFE script as Chome Mobile does not support Modules as Workers
// import Human from '../dist/human.esm.js';
self.importScripts('../../dist/human.js');
self.importScripts('../../node_modules/@tensorflow/tfjs-core/dist/tf-core.es2017.js');
self.importScripts('../../assets/tf-backend-webgpu.es2017.js');
let human;
onmessage = async (msg) => {
// received from index.js using:
// worker.postMessage({ image: image.data.buffer, width: canvas.width, height: canvas.height, config }, [image.data.buffer]);
// @ts-ignore // Human is registered as global namespace using IIFE script
// eslint-disable-next-line no-undef, new-cap
if (!human) human = new Human.default(msg.data.config);
const image = new ImageData(new Uint8ClampedArray(msg.data.image), msg.data.width, msg.data.height);
let result = {};
result = await human.detect(image, msg.data.config);
// @ts-ignore tslint wrong type matching for worker
postMessage({ result: result[msg.data.type], type: msg.data.type });
};

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
dist/human.esm.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
dist/human.js vendored

File diff suppressed because one or more lines are too long

View File

@ -11395,18 +11395,29 @@ var Human = class {
const timeStamp = now();
this.state = "backend";
if (this.config.backend && this.config.backend.length > 0) {
if (typeof window === "undefined" && typeof WorkerGlobalScope !== "undefined" && this.config.debug)
if (typeof window === "undefined" && typeof WorkerGlobalScope !== "undefined" && this.config.debug) {
log("running inside web worker");
}
if (this.tf.ENV.flags.IS_BROWSER && this.config.backend === "tensorflow") {
if (this.config.debug)
log("override: backend set to tensorflow while running in browser");
log("override: backend set to tensorflow while running in browser");
this.config.backend = "humangl";
}
if (this.tf.ENV.flags.IS_NODE && (this.config.backend === "webgl" || this.config.backend === "humangl")) {
if (this.config.debug)
log("override: backend set to webgl while running in nodejs");
log("override: backend set to webgl while running in nodejs");
this.config.backend = "tensorflow";
}
if (this.tf.ENV.flags.IS_BROWSER && this.config.backend === "webgpu") {
if (typeof navigator === "undefined" || typeof navigator["gpu"] === "undefined") {
log("override: backend set to webgpu but browser does not support webgpu");
this.config.backend = "humangl";
} else {
const adapter = await navigator["gpu"].requestAdapter();
if (this.config.debug)
log("enumerated webgpu adapter:", adapter);
}
}
if (this.config.backend === "humangl")
register();
const available = Object.keys(this.tf.engine().registryFactory);
if (this.config.debug)
log("available backends:", available);
@ -11431,15 +11442,12 @@ var Human = class {
if (this.config.debug && !simd)
log("warning: wasm simd support is not enabled");
}
if (this.config.backend === "humangl")
register();
try {
await this.tf.setBackend(this.config.backend);
} catch (err) {
log("error: cannot set backend:", this.config.backend, err);
}
}
this.tf.enableProdMode();
if (this.tf.getBackend() === "webgl" || this.tf.getBackend() === "humangl") {
this.tf.ENV.set("CHECK_COMPUTATION_FOR_ERRORS", false);
this.tf.ENV.set("WEBGL_CPU_FORWARD", true);
@ -11453,6 +11461,7 @@ var Human = class {
if (this.config.debug)
log(`gl version:${gl.getParameter(gl.VERSION)} renderer:${gl.getParameter(gl.RENDERER)}`);
}
this.tf.enableProdMode();
await this.tf.ready();
this.performance.backend = Math.trunc(now() - timeStamp);
}

View File

@ -11396,18 +11396,29 @@ var Human = class {
const timeStamp = now();
this.state = "backend";
if (this.config.backend && this.config.backend.length > 0) {
if (typeof window === "undefined" && typeof WorkerGlobalScope !== "undefined" && this.config.debug)
if (typeof window === "undefined" && typeof WorkerGlobalScope !== "undefined" && this.config.debug) {
log("running inside web worker");
}
if (this.tf.ENV.flags.IS_BROWSER && this.config.backend === "tensorflow") {
if (this.config.debug)
log("override: backend set to tensorflow while running in browser");
log("override: backend set to tensorflow while running in browser");
this.config.backend = "humangl";
}
if (this.tf.ENV.flags.IS_NODE && (this.config.backend === "webgl" || this.config.backend === "humangl")) {
if (this.config.debug)
log("override: backend set to webgl while running in nodejs");
log("override: backend set to webgl while running in nodejs");
this.config.backend = "tensorflow";
}
if (this.tf.ENV.flags.IS_BROWSER && this.config.backend === "webgpu") {
if (typeof navigator === "undefined" || typeof navigator["gpu"] === "undefined") {
log("override: backend set to webgpu but browser does not support webgpu");
this.config.backend = "humangl";
} else {
const adapter = await navigator["gpu"].requestAdapter();
if (this.config.debug)
log("enumerated webgpu adapter:", adapter);
}
}
if (this.config.backend === "humangl")
register();
const available = Object.keys(this.tf.engine().registryFactory);
if (this.config.debug)
log("available backends:", available);
@ -11432,15 +11443,12 @@ var Human = class {
if (this.config.debug && !simd)
log("warning: wasm simd support is not enabled");
}
if (this.config.backend === "humangl")
register();
try {
await this.tf.setBackend(this.config.backend);
} catch (err) {
log("error: cannot set backend:", this.config.backend, err);
}
}
this.tf.enableProdMode();
if (this.tf.getBackend() === "webgl" || this.tf.getBackend() === "humangl") {
this.tf.ENV.set("CHECK_COMPUTATION_FOR_ERRORS", false);
this.tf.ENV.set("WEBGL_CPU_FORWARD", true);
@ -11454,6 +11462,7 @@ var Human = class {
if (this.config.debug)
log(`gl version:${gl.getParameter(gl.VERSION)} renderer:${gl.getParameter(gl.RENDERER)}`);
}
this.tf.enableProdMode();
await this.tf.ready();
this.performance.backend = Math.trunc(now() - timeStamp);
}

25
dist/human.node.js vendored
View File

@ -11395,18 +11395,29 @@ var Human = class {
const timeStamp = now();
this.state = "backend";
if (this.config.backend && this.config.backend.length > 0) {
if (typeof window === "undefined" && typeof WorkerGlobalScope !== "undefined" && this.config.debug)
if (typeof window === "undefined" && typeof WorkerGlobalScope !== "undefined" && this.config.debug) {
log("running inside web worker");
}
if (this.tf.ENV.flags.IS_BROWSER && this.config.backend === "tensorflow") {
if (this.config.debug)
log("override: backend set to tensorflow while running in browser");
log("override: backend set to tensorflow while running in browser");
this.config.backend = "humangl";
}
if (this.tf.ENV.flags.IS_NODE && (this.config.backend === "webgl" || this.config.backend === "humangl")) {
if (this.config.debug)
log("override: backend set to webgl while running in nodejs");
log("override: backend set to webgl while running in nodejs");
this.config.backend = "tensorflow";
}
if (this.tf.ENV.flags.IS_BROWSER && this.config.backend === "webgpu") {
if (typeof navigator === "undefined" || typeof navigator["gpu"] === "undefined") {
log("override: backend set to webgpu but browser does not support webgpu");
this.config.backend = "humangl";
} else {
const adapter = await navigator["gpu"].requestAdapter();
if (this.config.debug)
log("enumerated webgpu adapter:", adapter);
}
}
if (this.config.backend === "humangl")
register();
const available = Object.keys(this.tf.engine().registryFactory);
if (this.config.debug)
log("available backends:", available);
@ -11431,15 +11442,12 @@ var Human = class {
if (this.config.debug && !simd)
log("warning: wasm simd support is not enabled");
}
if (this.config.backend === "humangl")
register();
try {
await this.tf.setBackend(this.config.backend);
} catch (err) {
log("error: cannot set backend:", this.config.backend, err);
}
}
this.tf.enableProdMode();
if (this.tf.getBackend() === "webgl" || this.tf.getBackend() === "humangl") {
this.tf.ENV.set("CHECK_COMPUTATION_FOR_ERRORS", false);
this.tf.ENV.set("WEBGL_CPU_FORWARD", true);
@ -11453,6 +11461,7 @@ var Human = class {
if (this.config.debug)
log(`gl version:${gl.getParameter(gl.VERSION)} renderer:${gl.getParameter(gl.RENDERER)}`);
}
this.tf.enableProdMode();
await this.tf.ready();
this.performance.backend = Math.trunc(now() - timeStamp);
}

View File

@ -1,22 +1,22 @@
2021-08-14 17:59:16 INFO:  @vladmandic/human version 2.1.3
2021-08-14 17:59:16 INFO:  User: vlado Platform: linux Arch: x64 Node: v16.5.0
2021-08-14 17:59:16 INFO:  Toolchain: {"tfjs":"3.8.0","esbuild":"0.12.20","typescript":"4.3.5","typedoc":"0.21.5","eslint":"7.32.0"}
2021-08-14 17:59:16 INFO:  Clean: ["dist/*","types/*","typedoc/*"]
2021-08-14 17:59:16 INFO:  Build: file startup all type: production config: {"minifyWhitespace":true,"minifyIdentifiers":true,"minifySyntax":true}
2021-08-14 17:59:16 STATE: target: node type: tfjs: {"imports":1,"importBytes":102,"outputBytes":1303,"outputFiles":"dist/tfjs.esm.js"}
2021-08-14 17:59:16 STATE: target: node type: node: {"imports":42,"importBytes":437259,"outputBytes":379053,"outputFiles":"dist/human.node.js"}
2021-08-14 17:59:16 STATE: target: nodeGPU type: tfjs: {"imports":1,"importBytes":110,"outputBytes":1311,"outputFiles":"dist/tfjs.esm.js"}
2021-08-14 17:59:16 STATE: target: nodeGPU type: node: {"imports":42,"importBytes":437267,"outputBytes":379057,"outputFiles":"dist/human.node-gpu.js"}
2021-08-14 17:59:16 STATE: target: nodeWASM type: tfjs: {"imports":1,"importBytes":149,"outputBytes":1378,"outputFiles":"dist/tfjs.esm.js"}
2021-08-14 17:59:16 STATE: target: nodeWASM type: node: {"imports":42,"importBytes":437334,"outputBytes":379129,"outputFiles":"dist/human.node-wasm.js"}
2021-08-14 17:59:16 STATE: target: browserNoBundle type: tfjs: {"imports":1,"importBytes":2168,"outputBytes":1242,"outputFiles":"dist/tfjs.esm.js"}
2021-08-14 17:59:16 STATE: target: browserNoBundle type: esm: {"imports":42,"importBytes":437198,"outputBytes":248711,"outputFiles":"dist/human.esm-nobundle.js"}
2021-08-14 17:59:17 STATE: target: browserBundle type: tfjs: {"modules":1170,"moduleBytes":4145868,"imports":7,"importBytes":2168,"outputBytes":2334701,"outputFiles":"dist/tfjs.esm.js"}
2021-08-14 17:59:17 STATE: target: browserBundle type: iife: {"imports":42,"importBytes":2770657,"outputBytes":1379075,"outputFiles":"dist/human.js"}
2021-08-14 17:59:18 STATE: target: browserBundle type: esm: {"imports":42,"importBytes":2770657,"outputBytes":1379067,"outputFiles":"dist/human.esm.js"}
2021-08-14 17:59:18 INFO:  Running Linter: ["server/","src/","tfjs/","test/","demo/"]
2021-08-14 17:59:40 INFO:  Linter complete: files: 76 errors: 0 warnings: 0
2021-08-14 17:59:40 INFO:  Generate ChangeLog: ["/home/vlado/dev/human/CHANGELOG.md"]
2021-08-14 17:59:40 INFO:  Generate Typings: ["src/human.ts"] outDir: ["types"]
2021-08-14 17:59:54 INFO:  Generate TypeDocs: ["src/human.ts"] outDir: ["typedoc"]
2021-08-14 18:00:09 INFO:  Documentation generated at /home/vlado/dev/human/typedoc 1
2021-08-15 08:08:32 INFO:  @vladmandic/human version 2.1.3
2021-08-15 08:08:32 INFO:  User: vlado Platform: linux Arch: x64 Node: v16.5.0
2021-08-15 08:08:32 INFO:  Toolchain: {"tfjs":"3.8.0","esbuild":"0.12.20","typescript":"4.3.5","typedoc":"0.21.5","eslint":"7.32.0"}
2021-08-15 08:08:32 INFO:  Clean: ["dist/*","types/*","typedoc/*"]
2021-08-15 08:08:32 INFO:  Build: file startup all type: production config: {"minifyWhitespace":true,"minifyIdentifiers":true,"minifySyntax":true}
2021-08-15 08:08:32 STATE: target: node type: tfjs: {"imports":1,"importBytes":102,"outputBytes":1303,"outputFiles":"dist/tfjs.esm.js"}
2021-08-15 08:08:32 STATE: target: node type: node: {"imports":42,"importBytes":437903,"outputBytes":379522,"outputFiles":"dist/human.node.js"}
2021-08-15 08:08:32 STATE: target: nodeGPU type: tfjs: {"imports":1,"importBytes":110,"outputBytes":1311,"outputFiles":"dist/tfjs.esm.js"}
2021-08-15 08:08:32 STATE: target: nodeGPU type: node: {"imports":42,"importBytes":437911,"outputBytes":379526,"outputFiles":"dist/human.node-gpu.js"}
2021-08-15 08:08:32 STATE: target: nodeWASM type: tfjs: {"imports":1,"importBytes":149,"outputBytes":1378,"outputFiles":"dist/tfjs.esm.js"}
2021-08-15 08:08:33 STATE: target: nodeWASM type: node: {"imports":42,"importBytes":437978,"outputBytes":379598,"outputFiles":"dist/human.node-wasm.js"}
2021-08-15 08:08:33 STATE: target: browserNoBundle type: tfjs: {"imports":1,"importBytes":2168,"outputBytes":1242,"outputFiles":"dist/tfjs.esm.js"}
2021-08-15 08:08:33 STATE: target: browserNoBundle type: esm: {"imports":42,"importBytes":437842,"outputBytes":249009,"outputFiles":"dist/human.esm-nobundle.js"}
2021-08-15 08:08:33 STATE: target: browserBundle type: tfjs: {"modules":1170,"moduleBytes":4145868,"imports":7,"importBytes":2168,"outputBytes":2334701,"outputFiles":"dist/tfjs.esm.js"}
2021-08-15 08:08:33 STATE: target: browserBundle type: iife: {"imports":42,"importBytes":2771301,"outputBytes":1379375,"outputFiles":"dist/human.js"}
2021-08-15 08:08:34 STATE: target: browserBundle type: esm: {"imports":42,"importBytes":2771301,"outputBytes":1379367,"outputFiles":"dist/human.esm.js"}
2021-08-15 08:08:34 INFO:  Running Linter: ["server/","src/","tfjs/","test/","demo/"]
2021-08-15 08:08:57 INFO:  Linter complete: files: 77 errors: 0 warnings: 0
2021-08-15 08:08:57 INFO:  Generate ChangeLog: ["/home/vlado/dev/human/CHANGELOG.md"]
2021-08-15 08:08:57 INFO:  Generate Typings: ["src/human.ts"] outDir: ["types"]
2021-08-15 08:09:11 INFO:  Generate TypeDocs: ["src/human.ts"] outDir: ["typedoc"]
2021-08-15 08:09:25 INFO:  Documentation generated at /home/vlado/dev/human/typedoc 1

View File

@ -9,7 +9,7 @@
*/
export interface Config {
/** Backend used for TFJS operations */
backend: null | '' | 'cpu' | 'wasm' | 'webgl' | 'humangl' | 'tensorflow',
backend: null | '' | 'cpu' | 'wasm' | 'webgl' | 'humangl' | 'tensorflow' | 'webgpu',
/** Path to *.wasm files if backend is set to `wasm` */
wasmPath: string,

View File

@ -298,19 +298,35 @@ export class Human {
*/
if (this.config.backend && this.config.backend.length > 0) {
// detect web worker
// @ts-ignore ignore missing type for WorkerGlobalScope as that is the point
if (typeof window === 'undefined' && typeof WorkerGlobalScope !== 'undefined' && this.config.debug) log('running inside web worker');
if (typeof window === 'undefined' && typeof WorkerGlobalScope !== 'undefined' && this.config.debug) {
log('running inside web worker');
}
// force browser vs node backend
if (this.tf.ENV.flags.IS_BROWSER && this.config.backend === 'tensorflow') {
if (this.config.debug) log('override: backend set to tensorflow while running in browser');
log('override: backend set to tensorflow while running in browser');
this.config.backend = 'humangl';
}
if (this.tf.ENV.flags.IS_NODE && (this.config.backend === 'webgl' || this.config.backend === 'humangl')) {
if (this.config.debug) log('override: backend set to webgl while running in nodejs');
log('override: backend set to webgl while running in nodejs');
this.config.backend = 'tensorflow';
}
// handle webgpu
if (this.tf.ENV.flags.IS_BROWSER && this.config.backend === 'webgpu') {
if (typeof navigator === 'undefined' || typeof navigator['gpu'] === 'undefined') {
log('override: backend set to webgpu but browser does not support webgpu');
this.config.backend = 'humangl';
} else {
const adapter = await navigator['gpu'].requestAdapter();
if (this.config.debug) log('enumerated webgpu adapter:', adapter);
}
}
// check available backends
if (this.config.backend === 'humangl') backend.register();
const available = Object.keys(this.tf.engine().registryFactory);
if (this.config.debug) log('available backends:', available);
@ -322,6 +338,7 @@ export class Human {
if (this.config.debug) log('setting backend:', this.config.backend);
// handle wasm
if (this.config.backend === 'wasm') {
if (this.config.debug) log('wasm path:', this.config.wasmPath);
if (typeof this.tf?.setWasmPaths !== 'undefined') this.tf.setWasmPaths(this.config.wasmPath);
@ -332,15 +349,15 @@ export class Human {
if (this.config.debug && !simd) log('warning: wasm simd support is not enabled');
}
if (this.config.backend === 'humangl') backend.register();
// handle humangl
try {
await this.tf.setBackend(this.config.backend);
} catch (err) {
log('error: cannot set backend:', this.config.backend, err);
}
}
this.tf.enableProdMode();
// this.tf.enableDebugMode();
// handle webgl & humangl
if (this.tf.getBackend() === 'webgl' || this.tf.getBackend() === 'humangl') {
this.tf.ENV.set('CHECK_COMPUTATION_FOR_ERRORS', false);
this.tf.ENV.set('WEBGL_CPU_FORWARD', true);
@ -355,6 +372,9 @@ export class Human {
const gl = await this.tf.backend().getGPGPUContext().gl;
if (this.config.debug) log(`gl version:${gl.getParameter(gl.VERSION)} renderer:${gl.getParameter(gl.RENDERER)}`);
}
// wait for ready
this.tf.enableProdMode();
await this.tf.ready();
this.performance.backend = Math.trunc(now() - timeStamp);
}

View File

@ -123,7 +123,7 @@
<section class="tsd-panel tsd-member tsd-kind-property tsd-parent-kind-interface">
<a name="backend" class="tsd-anchor"></a>
<h3>backend</h3>
<div class="tsd-signature tsd-kind-icon">backend<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">null</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">&quot;&quot;</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">&quot;cpu&quot;</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">&quot;wasm&quot;</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">&quot;webgl&quot;</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">&quot;humangl&quot;</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">&quot;tensorflow&quot;</span></div>
<div class="tsd-signature tsd-kind-icon">backend<span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">null</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">&quot;&quot;</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">&quot;cpu&quot;</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">&quot;wasm&quot;</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">&quot;webgl&quot;</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">&quot;humangl&quot;</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">&quot;tensorflow&quot;</span><span class="tsd-signature-symbol"> | </span><span class="tsd-signature-type">&quot;webgpu&quot;</span></div>
<aside class="tsd-sources">
</aside>
<div class="tsd-comment tsd-typography">

View File

@ -6,7 +6,7 @@
*/
export interface Config {
/** Backend used for TFJS operations */
backend: null | '' | 'cpu' | 'wasm' | 'webgl' | 'humangl' | 'tensorflow';
backend: null | '' | 'cpu' | 'wasm' | 'webgl' | 'humangl' | 'tensorflow' | 'webgpu';
/** Path to *.wasm files if backend is set to `wasm` */
wasmPath: string;
/** Print debug statements to console */