2021-04-27 07:04:25 +00:00
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
|
// Licensed under the MIT License.
|
|
|
|
|
|
2024-08-14 23:51:22 +00:00
|
|
|
import { env } from 'onnxruntime-common';
|
2022-05-04 06:41:36 +00:00
|
|
|
|
2024-08-14 23:51:22 +00:00
|
|
|
import { Backend, SessionHandler } from '../backend';
|
|
|
|
|
import { Logger } from '../instrument';
|
|
|
|
|
import { Session } from '../session';
|
2021-04-27 07:04:25 +00:00
|
|
|
|
2024-08-14 23:51:22 +00:00
|
|
|
import { WebGLSessionHandler } from './webgl/session-handler';
|
|
|
|
|
import { WebGLContext } from './webgl/webgl-context';
|
|
|
|
|
import { createWebGLContext } from './webgl/webgl-context-factory';
|
2021-04-27 07:04:25 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* WebGLBackend is the entry point for all WebGL opeartions
|
|
|
|
|
* When it starts it created the WebGLRenderingContext
|
|
|
|
|
* and other main framework components such as Program and Texture Managers
|
|
|
|
|
*/
|
|
|
|
|
export class WebGLBackend implements Backend {
|
|
|
|
|
glContext: WebGLContext;
|
|
|
|
|
|
2024-08-14 23:51:22 +00:00
|
|
|
get contextId(): 'webgl' | 'webgl2' | undefined {
|
2021-05-07 19:12:37 +00:00
|
|
|
return env.webgl.contextId;
|
2021-04-27 07:04:25 +00:00
|
|
|
}
|
2024-08-14 23:51:22 +00:00
|
|
|
set contextId(value: 'webgl' | 'webgl2' | undefined) {
|
2021-05-07 19:12:37 +00:00
|
|
|
env.webgl.contextId = value;
|
2021-04-27 07:04:25 +00:00
|
|
|
}
|
|
|
|
|
|
2024-08-14 23:51:22 +00:00
|
|
|
get matmulMaxBatchSize(): number | undefined {
|
2021-05-07 19:12:37 +00:00
|
|
|
return env.webgl.matmulMaxBatchSize;
|
2021-04-27 07:04:25 +00:00
|
|
|
}
|
2024-08-14 23:51:22 +00:00
|
|
|
set matmulMaxBatchSize(value: number | undefined) {
|
2021-05-07 19:12:37 +00:00
|
|
|
env.webgl.matmulMaxBatchSize = value;
|
2021-04-27 07:04:25 +00:00
|
|
|
}
|
|
|
|
|
|
2024-08-14 23:51:22 +00:00
|
|
|
get textureCacheMode(): 'initializerOnly' | 'full' | undefined {
|
2021-05-07 19:12:37 +00:00
|
|
|
return env.webgl.textureCacheMode;
|
2021-04-27 07:04:25 +00:00
|
|
|
}
|
2024-08-14 23:51:22 +00:00
|
|
|
set textureCacheMode(value: 'initializerOnly' | 'full' | undefined) {
|
2021-05-07 19:12:37 +00:00
|
|
|
env.webgl.textureCacheMode = value;
|
2021-04-27 07:04:25 +00:00
|
|
|
}
|
|
|
|
|
|
2024-08-14 23:51:22 +00:00
|
|
|
get pack(): boolean | undefined {
|
2021-05-07 19:12:37 +00:00
|
|
|
return env.webgl.pack;
|
2021-04-27 07:04:25 +00:00
|
|
|
}
|
2024-08-14 23:51:22 +00:00
|
|
|
set pack(value: boolean | undefined) {
|
2021-05-07 19:12:37 +00:00
|
|
|
env.webgl.pack = value;
|
2021-04-27 07:04:25 +00:00
|
|
|
}
|
|
|
|
|
|
2024-08-14 23:51:22 +00:00
|
|
|
get async(): boolean | undefined {
|
2021-09-10 05:17:42 +00:00
|
|
|
return env.webgl.async;
|
|
|
|
|
}
|
2024-08-14 23:51:22 +00:00
|
|
|
set async(value: boolean | undefined) {
|
2021-09-10 05:17:42 +00:00
|
|
|
env.webgl.async = value;
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-27 07:04:25 +00:00
|
|
|
initialize(): boolean {
|
|
|
|
|
try {
|
|
|
|
|
this.glContext = createWebGLContext(this.contextId);
|
|
|
|
|
if (typeof this.matmulMaxBatchSize !== 'number') {
|
|
|
|
|
this.matmulMaxBatchSize = 16;
|
|
|
|
|
}
|
|
|
|
|
if (typeof this.textureCacheMode !== 'string') {
|
|
|
|
|
this.textureCacheMode = 'full';
|
|
|
|
|
}
|
|
|
|
|
if (typeof this.pack !== 'boolean') {
|
|
|
|
|
this.pack = false;
|
|
|
|
|
}
|
2021-09-10 05:17:42 +00:00
|
|
|
if (typeof this.async !== 'boolean') {
|
|
|
|
|
this.async = false;
|
|
|
|
|
}
|
2021-05-17 21:16:59 +00:00
|
|
|
|
|
|
|
|
Logger.setWithEnv(env);
|
|
|
|
|
|
2023-10-06 20:37:37 +00:00
|
|
|
if (!env.webgl.context) {
|
2024-08-14 23:51:22 +00:00
|
|
|
Object.defineProperty(env.webgl, 'context', { value: this.glContext.gl });
|
2023-10-06 20:37:37 +00:00
|
|
|
}
|
[js/api] introducing IO binding for tensor (#16452)
[//]: # (## Work In Progress. Feedbacks are welcome!)
### Description
This PR adds a few properties, methods and factories to Tensor type to
support IO-binding feature. This will allow user to create tensor from
GPU/CPU bound data without a force transferring of data between CPU and
GPU.
This change is a way to resolve #15312
### Change Summary
1. Add properties to `Tensor` type:
a. `location`: indicating where the data is sitting. valid values are
`cpu`, `cpu-pinned`, `texture`, `gpu-buffer`.
b. `texture`: sit side to `data`, a readonly property of `WebGLTexture`
type. available only when `location === 'texture'`
c. `gpuBuffer`: sit side to `data`, a readonly property of `GPUBuffer`
type. available only when `location === 'gpu-buffer'`
2. Add methods to `Tensor` type (usually dealing with inference
outputs):
- async function `getData()` allows user to download data from GPU to
CPU manually.
- function `dispose()` allows user to release GPU resources manually.
3. Add factories for creating `Tensor` instances:
a. `fromTexture()` to create a WebGL texture bound tensor data
b. `fromGpuBuffer()` to create a WebGPUBuffer bound tensor data
c. `fromPinnedBuffer()` to create a tensor using a CPU pinned buffer
### Examples:
create tensors from texture and pass to inference session as inputs
```js
// when create session, specify we prefer 'image_output:0' to be stored on GPU as texture
const session = await InferenceSession.create('./my_model.onnx', {
executionProviders: [ 'webgl' ],
preferredOutputLocation: { 'image_output:0': 'texture' }
});
...
const myImageTexture = getTexture(); // user's function to get a texture
const myFeeds = { input0: Tensor.fromTexture(myImageTexture, { width: 224, height: 224 }) }; // shape [1, 224, 224, 4], RGBA format.
const results = await session.run(myFeeds);
const myOutputTexture = results['image_output:0'].texture;
```
2023-08-29 19:58:26 +00:00
|
|
|
|
2021-04-27 07:04:25 +00:00
|
|
|
Logger.verbose(
|
2024-08-14 23:51:22 +00:00
|
|
|
'WebGLBackend',
|
|
|
|
|
`Created WebGLContext: ${typeof this.glContext} with matmulMaxBatchSize: ${
|
|
|
|
|
this.matmulMaxBatchSize
|
|
|
|
|
}; textureCacheMode: ${this.textureCacheMode}; pack: ${this.pack}; async: ${this.async}.`,
|
|
|
|
|
);
|
2021-04-27 07:04:25 +00:00
|
|
|
return true;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
Logger.warning('WebGLBackend', `Unable to initialize WebGLBackend. ${e}`);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
createSessionHandler(context: Session.Context): SessionHandler {
|
|
|
|
|
return new WebGLSessionHandler(this, context);
|
|
|
|
|
}
|
|
|
|
|
dispose(): void {
|
|
|
|
|
this.glContext.dispose();
|
|
|
|
|
}
|
|
|
|
|
}
|