fix(studio): the repair model runs in a worker where the phone has no device, so the page keeps answering fingers
This commit is contained in:
@@ -71,6 +71,23 @@ async function warmsUp(ort: typeof Ort, session: Ort.InferenceSession): Promise<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Whether the page has a device of its own to run the graph on. Asked of the
|
||||||
|
// browser rather than of the runtime: creating a session of any kind — the
|
||||||
|
// WebGPU one included — builds the wasm backend underneath it, and
|
||||||
|
// `env.wasm.proxy` is read at that moment. A proxy set after it is a proxy that
|
||||||
|
// never took, and every run of the fallback then ends the way it did the first
|
||||||
|
// time this was tried: `no available backend found. ERR: [wasm] Error: worker
|
||||||
|
// not ready`. So the question is put before anything is created.
|
||||||
|
async function hasDevice(): Promise<boolean> {
|
||||||
|
const gpu = (navigator as Navigator & { gpu?: { requestAdapter(): Promise<unknown> } }).gpu;
|
||||||
|
if (!gpu) return false;
|
||||||
|
try {
|
||||||
|
return !!(await gpu.requestAdapter());
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// WebGPU first, the processor as the answer to every way that can fail: no
|
// WebGPU first, the processor as the answer to every way that can fail: no
|
||||||
// adapter, no `shader-f16` needed here but an op the provider never
|
// adapter, no `shader-f16` needed here but an op the provider never
|
||||||
// implemented, a driver that opens a session and dies on the first dispatch.
|
// implemented, a driver that opens a session and dies on the first dispatch.
|
||||||
@@ -99,6 +116,16 @@ function load(): Promise<Loaded> {
|
|||||||
ort.env.wasm.numThreads = self.crossOriginIsolated
|
ort.env.wasm.numThreads = self.crossOriginIsolated
|
||||||
? Math.min(4, navigator.hardwareConcurrency || 1)
|
? Math.min(4, navigator.hardwareConcurrency || 1)
|
||||||
: 1;
|
: 1;
|
||||||
|
// The fallback's turn is taken in a worker of the page's own, wherever
|
||||||
|
// there is no device to take it on: a wasm run is seconds of arithmetic
|
||||||
|
// that never hands the thread back in the middle of it, and a thread that
|
||||||
|
// cannot answer a finger for three seconds is a tab a phone takes away
|
||||||
|
// (measured: 3.5s of frozen page per repair, on a desktop). Proxied, the
|
||||||
|
// page keeps its frames and its touches while the repair is worked out,
|
||||||
|
// and the repair lands under the spinner the studio already shows. It is
|
||||||
|
// left off where a device is there, because the WebGPU path is a device of
|
||||||
|
// its own and must be built on the page's own thread.
|
||||||
|
ort.env.wasm.proxy = !(await hasDevice());
|
||||||
ort.env.webgpu.powerPreference = 'high-performance';
|
ort.env.webgpu.powerPreference = 'high-performance';
|
||||||
const session = await openSession(ort);
|
const session = await openSession(ort);
|
||||||
return { ort, session };
|
return { ort, session };
|
||||||
|
|||||||
Reference in New Issue
Block a user