зеркало из https://github.com/microsoft/onnxjs.git
add texture cache support for pack/unpack mode (#290)
* squash change * uncomment test verification * clean up * clean up and remove unused files * adding comment * remove unused code * fix reshape merge * add guid as tensor id * add file * fix test failure
This commit is contained in:
Родитель
290825d28c
Коммит
0c998cc45e
|
@ -690,7 +690,7 @@ export class CoordsGlslLib extends GlslLib {
|
|||
return ${texFuncSnippet}(${unpackedCoordsSnippet});
|
||||
}
|
||||
`;
|
||||
return new GlslLibRoutine(source);
|
||||
return new GlslLibRoutine(source, ['coordinates.getOutputCoords']);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1216,4 +1216,27 @@ export class CoordsGlslLib extends GlslLib {
|
|||
}
|
||||
`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Produces a packed value getter function for the name and rank given
|
||||
* If a transpose is set proper offsetToCoords mapping will be used
|
||||
* @param name name of the function
|
||||
* @param rank rank of the input
|
||||
* @param transpose whether or not should generate a transpose variation
|
||||
*/
|
||||
protected getPackedValueFrom(varName: string, rank: number, width: number, height: number, transpose: boolean):
|
||||
string {
|
||||
let name = `_${varName}_Pack`;
|
||||
if (transpose) {
|
||||
name = name + '_T';
|
||||
}
|
||||
const glsl = getGlsl(this.context.glContext.version);
|
||||
return `
|
||||
vec4 ${name}(int m[${rank}]) {
|
||||
int offset = indicesToOffset_${varName}(m);
|
||||
vec2 coords = offsetToCoords(offset, ${width}, ${height});
|
||||
return ${glsl.texture2D}(${varName}, coords);
|
||||
}
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,9 +16,16 @@ import {Artifact, RunData, TextureData, TextureLayout, WebGLOperator} from './ty
|
|||
import {getPackedShape} from './utils';
|
||||
|
||||
export class WebGLInferenceHandler implements InferenceHandler {
|
||||
private textureDataCache: Map<Tensor.Id, TextureData>;
|
||||
private packedTextureDataCache: Map<Tensor.Id, TextureData>;
|
||||
private unpackedTextureDataCache: Map<Tensor.Id, TextureData>;
|
||||
private pack2unpackMap: Map<Tensor.Id, Tensor.Id>;
|
||||
private unpack2packMap: Map<Tensor.Id, Tensor.Id>;
|
||||
constructor(public session: WebGLSessionHandler) {
|
||||
this.textureDataCache = new Map();
|
||||
this.packedTextureDataCache = new Map();
|
||||
this.unpackedTextureDataCache = new Map();
|
||||
|
||||
this.pack2unpackMap = new Map();
|
||||
this.unpack2packMap = new Map();
|
||||
}
|
||||
|
||||
run(op: WebGLOperator, inputs: Tensor[]): Tensor[] {
|
||||
|
@ -33,36 +40,18 @@ export class WebGLInferenceHandler implements InferenceHandler {
|
|||
return [runData.outputTextureData.tensor];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the runData's input texture mode with the program's artifact.
|
||||
* If the artifact expects a packed input, while the RunData's input
|
||||
* is unpacked, perform a pack operation on this input to align the
|
||||
* texture mode with artifact. Similar on unpacked input.
|
||||
*/
|
||||
checkAndUpdateTextureForm(artifact: Artifact, runData: RunData) {
|
||||
// pack/unpack inputs
|
||||
runData.inputTextureDatas.forEach(input => {
|
||||
for (let i = 0; i < runData.inputTextureDatas.length; ++i) {
|
||||
const input = runData.inputTextureDatas[i];
|
||||
if (input.isPacked && !artifact.programInfo.expectPackedInputs) {
|
||||
// unpack this input
|
||||
const unpacked = this.unpack(input);
|
||||
input.height = unpacked.height;
|
||||
input.isPacked = unpacked.isPacked;
|
||||
input.texture = unpacked.texture;
|
||||
input.width = unpacked.width;
|
||||
|
||||
runData.inputTextureDatas[i] = this.unpack(input);
|
||||
} else if (!input.isPacked && artifact.programInfo.expectPackedInputs) {
|
||||
// pack this input
|
||||
const packed = this.pack(input);
|
||||
input.height = packed.height;
|
||||
input.isPacked = packed.isPacked;
|
||||
input.texture = packed.texture;
|
||||
input.width = packed.width;
|
||||
runData.inputTextureDatas[i] = this.pack(input);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
runProgram(artifact: Artifact, runData: RunData) {
|
||||
// if the runData has different expected texture pack/unpack mode, process pack/unpack
|
||||
// operation on the texture before executing the kernel.
|
||||
this.checkAndUpdateTextureForm(artifact, runData);
|
||||
|
||||
// output should match
|
||||
|
@ -84,15 +73,28 @@ export class WebGLInferenceHandler implements InferenceHandler {
|
|||
* Creates a texture data object associated with the given tensor.
|
||||
* @param tensor the tensor with data to upload
|
||||
*/
|
||||
getOrCreateTextureData(tensor: Tensor, layout?: TextureLayout) {
|
||||
let td = this.getTextureData(tensor.dataId);
|
||||
getOrCreateTextureData(tensor: Tensor, layout?: TextureLayout, isPacked = false) {
|
||||
let td = this.getTextureData(tensor.dataId, isPacked);
|
||||
if (!td) {
|
||||
Logger.verbose('InferenceHandler', `Creating new TextureData for dims: [${tensor.dims}]`);
|
||||
if (!layout) {
|
||||
layout = this.createTextureLayoutFromShape(tensor.dims.slice());
|
||||
}
|
||||
// graph inputs or initializers
|
||||
td = this.createTextureData(layout, tensor.type, tensor.numberData, tensor, Encoder.Usage.UploadOnly);
|
||||
// if we don't find the texture data with specific pack mode in the cache, try with the different
|
||||
// pack mode to see if the tensor is cached using that pack mode. If succeed, we can return this
|
||||
// tensor data and later apply a pack/unpack op on this texture, no need to create a new one here.
|
||||
td = this.getTextureData(tensor.dataId, !isPacked);
|
||||
if (!td) {
|
||||
if (isPacked) {
|
||||
const unpackedTextureLayout = this.getOrCreateTextureLayout(tensor, 1, false, [], true);
|
||||
const unpackedTextureData = this.createTextureData(
|
||||
unpackedTextureLayout, tensor.type, tensor.numberData, tensor, Encoder.Usage.UploadOnly);
|
||||
td = this.pack(unpackedTextureData);
|
||||
} else {
|
||||
td = this.createTextureData(
|
||||
layout, tensor.type, tensor.numberData, tensor, Encoder.Usage.UploadOnly, isPacked);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Logger.verbose('InferenceHandler', `Retrieving TextureData from cache: [${tensor.dims}]`);
|
||||
}
|
||||
|
@ -104,7 +106,7 @@ export class WebGLInferenceHandler implements InferenceHandler {
|
|||
* Usage = Encoder.Usage.Default.
|
||||
* @param dataType the tensor data type
|
||||
*/
|
||||
createTextureDataFromLayout(layout: TextureLayout, dataType: Tensor.DataType): TextureData {
|
||||
createTextureDataFromLayout(layout: TextureLayout, dataType: Tensor.DataType, isPacked = false): TextureData {
|
||||
return this.createTextureData(layout, dataType);
|
||||
}
|
||||
|
||||
|
@ -118,13 +120,14 @@ export class WebGLInferenceHandler implements InferenceHandler {
|
|||
* @param tensor the tensor to bind. tensor's data is ignored.
|
||||
*/
|
||||
createTextureDataFromLayoutBindTensor(
|
||||
layout: TextureLayout, dataType: Tensor.DataType, data: Tensor.NumberType, tensor: Tensor): TextureData {
|
||||
return this.createTextureData(layout, dataType, data, tensor, Encoder.Usage.UploadOnly);
|
||||
layout: TextureLayout, dataType: Tensor.DataType, data: Tensor.NumberType, tensor: Tensor,
|
||||
isPacked = false): TextureData {
|
||||
return this.createTextureData(layout, dataType, data, tensor, Encoder.Usage.UploadOnly, isPacked);
|
||||
}
|
||||
|
||||
private createTextureData(
|
||||
layout: TextureLayout, dataType: Tensor.DataType, data?: Tensor.NumberType, tensor?: Tensor,
|
||||
usage?: Encoder.Usage): TextureData {
|
||||
usage?: Encoder.Usage, isPacked = false): TextureData {
|
||||
Logger.verbose('InferenceHandler', `Creating TextureData: layout:[${JSON.stringify(layout)}]`);
|
||||
const texture = this.session.textureManager.createTextureFromLayout(dataType, layout, data, usage);
|
||||
return this.createTextureDataFromTexture(layout, dataType, texture, tensor);
|
||||
|
@ -137,8 +140,9 @@ export class WebGLInferenceHandler implements InferenceHandler {
|
|||
* @param texture the WebGLTexture object to share
|
||||
* @param tensorId the tensor ID of the shared tensor data
|
||||
*/
|
||||
createSharedTextureData(layout: TextureLayout, dataType: Tensor.DataType, texture: WebGLTexture, tensorId: Tensor.Id):
|
||||
TextureData {
|
||||
createSharedTextureData(
|
||||
layout: TextureLayout, dataType: Tensor.DataType, texture: WebGLTexture, tensorId?: Tensor.Id,
|
||||
isPacked = false): TextureData {
|
||||
return this.createTextureDataFromTexture(layout, dataType, texture, undefined, tensorId);
|
||||
}
|
||||
|
||||
|
@ -155,29 +159,32 @@ export class WebGLInferenceHandler implements InferenceHandler {
|
|||
undefined, undefined, tensorId),
|
||||
texture
|
||||
};
|
||||
this.setTextureData(textureData.tensor.dataId, textureData);
|
||||
this.setTextureData(textureData.tensor.dataId, textureData, layout.isPacked);
|
||||
return textureData;
|
||||
}
|
||||
|
||||
getTextureData(tensorId: Tensor.Id): TextureData|undefined {
|
||||
return this.session.isInitializer(tensorId) ? this.session.getTextureData(tensorId) :
|
||||
this.textureDataCache.get(tensorId);
|
||||
getTextureData(tensorId: Tensor.Id, isPacked = false): TextureData|undefined {
|
||||
return this.session.isInitializer(tensorId) ?
|
||||
this.session.getTextureData(tensorId, isPacked) :
|
||||
isPacked ? this.packedTextureDataCache.get(tensorId) : this.unpackedTextureDataCache.get(tensorId);
|
||||
}
|
||||
setTextureData(tensorId: Tensor.Id, td: TextureData): void {
|
||||
setTextureData(tensorId: Tensor.Id, td: TextureData, isPacked = false): void {
|
||||
if (this.session.isInitializer(tensorId)) {
|
||||
this.session.setTextureData(tensorId, td);
|
||||
this.session.setTextureData(tensorId, td, isPacked);
|
||||
} else {
|
||||
this.textureDataCache.set(tensorId, td);
|
||||
isPacked ? this.packedTextureDataCache.set(tensorId, td) : this.unpackedTextureDataCache.set(tensorId, td);
|
||||
}
|
||||
}
|
||||
|
||||
isTextureLayoutCached(tensor: Tensor, isPacked = false): boolean {
|
||||
return !!this.getTextureData(tensor.dataId, isPacked);
|
||||
}
|
||||
/**
|
||||
* Create a TextureLayout object from a tensor. If a related texture data is found, returns the cached texture layout.
|
||||
*/
|
||||
getOrCreateTextureLayout(
|
||||
tensor: Tensor, channels: 1|4 = 1, isPacked = false, unpackedShape?: ReadonlyArray<number>,
|
||||
reverseWH = false): TextureLayout {
|
||||
const td = this.getTextureData(tensor.dataId);
|
||||
const td = this.getTextureData(tensor.dataId, isPacked);
|
||||
if (td) {
|
||||
return td;
|
||||
}
|
||||
|
@ -229,14 +236,17 @@ export class WebGLInferenceHandler implements InferenceHandler {
|
|||
isPacked,
|
||||
shape: inferredDims,
|
||||
strides: ShapeUtil.computeStrides(inferredDims),
|
||||
unpackedShape
|
||||
unpackedShape,
|
||||
reversedWH: (prefs && prefs.reverseWH)
|
||||
};
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.session.textureManager.clearActiveTextures();
|
||||
this.textureDataCache.forEach(td => this.session.textureManager.releaseTexture(td));
|
||||
this.textureDataCache = new Map();
|
||||
this.packedTextureDataCache.forEach(td => this.session.textureManager.releaseTexture(td));
|
||||
this.packedTextureDataCache = new Map();
|
||||
this.unpackedTextureDataCache.forEach(td => this.session.textureManager.releaseTexture(td));
|
||||
this.unpackedTextureDataCache = new Map();
|
||||
}
|
||||
|
||||
readTexture(textureData: TextureData): Tensor.NumberType {
|
||||
|
@ -252,6 +262,10 @@ export class WebGLInferenceHandler implements InferenceHandler {
|
|||
}
|
||||
|
||||
pack(input: TextureData): TextureData {
|
||||
const cachedId = this.unpack2packMap.get(input.tensor.dataId);
|
||||
if (cachedId) {
|
||||
return this.packedTextureDataCache.get(cachedId)!;
|
||||
}
|
||||
const key = `${input.shape}`;
|
||||
let op = this.session.packOpCache.get(key);
|
||||
if (!op) {
|
||||
|
@ -266,10 +280,15 @@ export class WebGLInferenceHandler implements InferenceHandler {
|
|||
}
|
||||
const runData = op.createRunData(this, artifact.programInfo, [input.tensor]);
|
||||
this.runProgram(artifact, runData);
|
||||
this.unpack2packMap.set(input.tensor.dataId, runData.outputTextureData.tensor.dataId);
|
||||
return runData.outputTextureData;
|
||||
}
|
||||
|
||||
unpack(input: TextureData): TextureData {
|
||||
const cachedId = this.pack2unpackMap.get(input.tensor.dataId);
|
||||
if (cachedId) {
|
||||
return this.unpackedTextureDataCache.get(cachedId)!;
|
||||
}
|
||||
// For unpacked kernel, cache it by using input's unpackedShape as cache key.
|
||||
// Note that we need to use input.unpackedShape instead of input.shape here,
|
||||
// as the shape infers the packed texture shape. Different unpackedShape can have the
|
||||
|
@ -290,6 +309,7 @@ export class WebGLInferenceHandler implements InferenceHandler {
|
|||
}
|
||||
const runData = op.createRunData(this, artifact.programInfo, [input.tensor]);
|
||||
this.runProgram(artifact, runData);
|
||||
this.pack2unpackMap.set(input.tensor.dataId, runData.outputTextureData.tensor.dataId);
|
||||
return runData.outputTextureData;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,10 @@ export class WebGLBinaryOp extends BinaryOp implements WebGLOperator {
|
|||
const inputLayouts = handler.session.pack ?
|
||||
inputs.map(t => handler.getOrCreateTextureLayout(t, 4, true, t.dims, true)) :
|
||||
inputs.map(t => handler.getOrCreateTextureLayout(t));
|
||||
const ouputLayout = handler.session.pack ?
|
||||
handler.createTextureLayoutFromShape(inputs[0].dims, 4, inputs[0].dims, {isPacked: true, reverseWH: true}) :
|
||||
handler.createTextureLayoutFromShape(inputs[0].dims);
|
||||
|
||||
const isBroadcast = !ShapeUtil.areEqual(inputs[0].dims, inputs[1].dims);
|
||||
if (isBroadcast) {
|
||||
const outputShape = BroadcastUtil.calcShape(inputs[0].dims, inputs[1].dims, false);
|
||||
|
@ -33,6 +37,8 @@ export class WebGLBinaryOp extends BinaryOp implements WebGLOperator {
|
|||
const bRank = inputs[1].dims.length !== 0 ? inputs[1].dims.length : 1;
|
||||
const aBcast = inputs[0].dims.length !== 0 ? `bcastIndices_A(indices, aindices);` : `aindices[0] = 0;`;
|
||||
const bBcast = inputs[1].dims.length !== 0 ? `bcastIndices_B(indices, bindices);` : `bindices[0] = 0;`;
|
||||
|
||||
// TODO: for packed tensors, we need to implement logic to caculate textCoords for broadcast tensor
|
||||
const shaderSource = `
|
||||
${this.glslFunc.body}
|
||||
float process(int indices[${outputRank}]) {
|
||||
|
@ -51,6 +57,8 @@ export class WebGLBinaryOp extends BinaryOp implements WebGLOperator {
|
|||
outputLayout,
|
||||
samplers: ['A', 'B'],
|
||||
shaderSource,
|
||||
expectPackedInputs: handler.session.pack,
|
||||
expectPackedOutputs: handler.session.pack
|
||||
};
|
||||
}
|
||||
const glsl = getGlsl(handler.session.backend.glContext.version);
|
||||
|
@ -67,7 +75,7 @@ export class WebGLBinaryOp extends BinaryOp implements WebGLOperator {
|
|||
return {
|
||||
hasMain: true,
|
||||
inputLayouts,
|
||||
outputLayout: handler.createTextureLayoutFromShape(inputs[0].dims),
|
||||
outputLayout: ouputLayout,
|
||||
samplers: ['A', 'B'],
|
||||
shaderSource,
|
||||
expectPackedInputs: true,
|
||||
|
|
|
@ -117,10 +117,17 @@ export class WebGLReshapePacked extends Reshape implements WebGLOperator {
|
|||
createRunData(handler: WebGLInferenceHandler, programInfo: ProgramInfo, inputs: Tensor[]): RunData {
|
||||
const inputTDs =
|
||||
[handler.getOrCreateTextureData(inputs[0], handler.getOrCreateTextureLayout(inputs[0], 1, false, [], false))];
|
||||
let outputLayout = this.originalOutputLayout;
|
||||
if (outputLayout === undefined) {
|
||||
const originInputShape = inputs[0].dims;
|
||||
const outputShape = ShapeUtil.calculateReshapedDims(originInputShape, inputs[1].integerData);
|
||||
outputLayout =
|
||||
handler.createTextureLayoutFromShape(outputShape, 4, outputShape, {isPacked: true, reverseWH: true});
|
||||
}
|
||||
// return run data for reshape. Here, we use the original calculate outputLayout to create the real output layout.
|
||||
return {
|
||||
inputTextureDatas: inputTDs,
|
||||
outputTextureData: handler.createTextureDataFromLayout(this.originalOutputLayout, inputTDs[0].tensor.type),
|
||||
outputTextureData: handler.createTextureDataFromLayout(outputLayout, inputTDs[0].tensor.type),
|
||||
uniformData: {}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -43,6 +43,6 @@ export function reshape(
|
|||
unpackedShape: reshapedDims,
|
||||
};
|
||||
|
||||
const newTextureData = inferenceHandler.createSharedTextureData(newTextureLayout, input.type, inputTD.texture, {});
|
||||
const newTextureData = inferenceHandler.createSharedTextureData(newTextureLayout, input.type, inputTD.texture);
|
||||
return newTextureData.tensor;
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ export class WebGLUint8Encode {
|
|||
const encoder = inferenceHandler.session.backend.glContext.getEncoder('byte', 4);
|
||||
const texture =
|
||||
inferenceHandler.session.backend.glContext.allocateTexture(outputLayout.width, outputLayout.height, encoder);
|
||||
const outputTextureData = inferenceHandler.createSharedTextureData(outputLayout, 'uint8', texture, {});
|
||||
const outputTextureData = inferenceHandler.createSharedTextureData(outputLayout, 'uint8', texture);
|
||||
const runData = {inputTextureDatas: [input], outputTextureData, uniformData: {}};
|
||||
|
||||
inferenceHandler.session.programManager.run(artifact, runData);
|
||||
|
|
|
@ -6,7 +6,6 @@ import {getGlsl} from '../glsl-source';
|
|||
import {WebGLInferenceHandler} from '../inference-handler';
|
||||
import {ProgramInfo, RunData, WebGLOperator} from '../types';
|
||||
import {getCoordsDataType} from '../utils';
|
||||
|
||||
import {getChannels, unpackFromChannel} from './packing_utils';
|
||||
|
||||
export class WebGLUnpack implements WebGLOperator {
|
||||
|
@ -18,7 +17,7 @@ export class WebGLUnpack implements WebGLOperator {
|
|||
throw new Error(`Pack kernel should have input tensor count to 1.`);
|
||||
}
|
||||
|
||||
const inputTexture = handler.getTextureData(inputs[0].dataId);
|
||||
const inputTexture = handler.getTextureData(inputs[0].dataId, true);
|
||||
if (!inputTexture) {
|
||||
throw new Error(`packed input texture must exist`);
|
||||
}
|
||||
|
@ -49,7 +48,7 @@ export class WebGLUnpack implements WebGLOperator {
|
|||
`;
|
||||
|
||||
return {
|
||||
inputLayouts: [handler.getOrCreateTextureLayout(inputs[0])],
|
||||
inputLayouts: [handler.getOrCreateTextureLayout(inputs[0], 4, true, inputs[0].dims, true)],
|
||||
outputLayout,
|
||||
samplers: ['A'],
|
||||
shaderSource,
|
||||
|
@ -59,7 +58,7 @@ export class WebGLUnpack implements WebGLOperator {
|
|||
};
|
||||
}
|
||||
createRunData(handler: WebGLInferenceHandler, programInfo: ProgramInfo, inputs: Tensor[]): RunData {
|
||||
const inputTDs = [handler.getOrCreateTextureData(inputs[0], programInfo.inputLayouts[0])];
|
||||
const inputTDs = [handler.getOrCreateTextureData(inputs[0], programInfo.inputLayouts[0], true)];
|
||||
return {
|
||||
inputTextureDatas: inputTDs,
|
||||
outputTextureData: handler.createTextureDataFromLayout(programInfo.outputLayout, inputTDs[0].tensor.type),
|
||||
|
|
|
@ -105,11 +105,12 @@ ${fragShaderScript}
|
|||
return program;
|
||||
}
|
||||
bindOutput(td: TextureData): void {
|
||||
const width = td.width;
|
||||
const height = td.height;
|
||||
Logger.verbose(
|
||||
'ProrgramManager',
|
||||
`Binding output texture to Framebuffer: w/h=${td.width}/${td.height}, shape=${td.shape}, type=${
|
||||
td.tensor.type}`);
|
||||
this.glContext.attachFramebuffer(td.texture, td.width, td.height);
|
||||
`Binding output texture to Framebuffer: w/h=${width}/${height}, shape=${td.shape}, type=${td.tensor.type}`);
|
||||
this.glContext.attachFramebuffer(td.texture, width, height);
|
||||
}
|
||||
bindAttributes(attribLocations: Artifact.AttribLocations): void {
|
||||
const positionHandle = attribLocations.position;
|
||||
|
|
|
@ -21,7 +21,10 @@ export class WebGLSessionHandler implements SessionHandler {
|
|||
programManager: ProgramManager;
|
||||
textureManager: TextureManager;
|
||||
layoutStrategy: TextureLayoutStrategy;
|
||||
textureDataCache: Map<Tensor.Id, TextureData>;
|
||||
packedTextureDataCache: Map<Tensor.Id, TextureData>;
|
||||
unpackedTextureDataCache: Map<Tensor.Id, TextureData>;
|
||||
pack2unpackMap: Map<Tensor.Id, Tensor.Id>;
|
||||
unpack2packMap: Map<Tensor.Id, Tensor.Id>;
|
||||
initializers: Set<Tensor.Id>;
|
||||
packOpCache: Map<string, WebGLOperator>;
|
||||
unpackOpCache: Map<string, WebGLOperator>;
|
||||
|
@ -33,10 +36,13 @@ export class WebGLSessionHandler implements SessionHandler {
|
|||
this.textureManager = new TextureManager(
|
||||
backend.glContext, this.layoutStrategy, this.context.profiler,
|
||||
{reuseTextures: backend.textureCacheMode === 'full'});
|
||||
this.textureDataCache = new Map();
|
||||
this.packedTextureDataCache = new Map();
|
||||
this.unpackedTextureDataCache = new Map();
|
||||
this.packOpCache = new Map();
|
||||
this.unpackOpCache = new Map();
|
||||
this.pack = backend.pack;
|
||||
this.pack2unpackMap = new Map();
|
||||
this.unpack2packMap = new Map();
|
||||
}
|
||||
|
||||
createInferenceHandler() {
|
||||
|
@ -49,18 +55,31 @@ export class WebGLSessionHandler implements SessionHandler {
|
|||
isInitializer(tensorId: Tensor.Id): boolean {
|
||||
return this.initializers ? this.initializers.has(tensorId) : false;
|
||||
}
|
||||
getTextureData(tensorId: Tensor.Id): TextureData|undefined {
|
||||
return this.textureDataCache.get(tensorId);
|
||||
addInitializer(tensorId: Tensor.Id): void {
|
||||
this.initializers.add(tensorId);
|
||||
}
|
||||
setTextureData(tensorId: Tensor.Id, textureData: TextureData): void {
|
||||
getTextureData(tensorId: Tensor.Id, isPacked: boolean): TextureData|undefined {
|
||||
if (isPacked) {
|
||||
return this.packedTextureDataCache.get(tensorId);
|
||||
} else {
|
||||
return this.unpackedTextureDataCache.get(tensorId);
|
||||
}
|
||||
}
|
||||
setTextureData(tensorId: Tensor.Id, textureData: TextureData, isPacked = false): void {
|
||||
Logger.verbose('WebGLSessionHandler', 'Storing Texture data in cache');
|
||||
this.textureDataCache.set(tensorId, textureData);
|
||||
if (isPacked) {
|
||||
this.packedTextureDataCache.set(tensorId, textureData);
|
||||
} else {
|
||||
this.unpackedTextureDataCache.set(tensorId, textureData);
|
||||
}
|
||||
}
|
||||
dispose(): void {
|
||||
this.programManager.dispose();
|
||||
this.textureManager.clearActiveTextures();
|
||||
this.textureDataCache.forEach(td => this.textureManager.releaseTexture(td, true));
|
||||
this.textureDataCache = new Map();
|
||||
this.packedTextureDataCache.forEach(td => this.textureManager.releaseTexture(td, true));
|
||||
this.packedTextureDataCache = new Map();
|
||||
this.unpackedTextureDataCache.forEach(td => this.textureManager.releaseTexture(td, true));
|
||||
this.unpackedTextureDataCache = new Map();
|
||||
}
|
||||
resolve(node: Graph.Node, opsets: ReadonlyArray<OpSet>, graph: Graph): Operator {
|
||||
const op = resolveOperator(node, opsets, WEBGL_OP_RESOLVE_RULES);
|
||||
|
|
|
@ -196,7 +196,6 @@ export function parseAxisParam(axis: number|number[], shape: number[]): number[]
|
|||
// Handle negative axis.
|
||||
return axis.map(a => a < 0 ? rank + a : a);
|
||||
}
|
||||
|
||||
export function isInt(a: number): boolean {
|
||||
return a % 1 === 0;
|
||||
}
|
||||
|
|
|
@ -42,6 +42,8 @@ export interface TextureLayout {
|
|||
* the original shape(dims) of the corresponding tensor
|
||||
*/
|
||||
unpackedShape: ReadonlyArray<number>;
|
||||
|
||||
reversedWH?: boolean;
|
||||
}
|
||||
export interface TextureData extends TextureLayout {
|
||||
tensor: Tensor;
|
||||
|
|
|
@ -1,13 +1,18 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
import {Guid} from 'guid-typescript';
|
||||
import Long from 'long';
|
||||
import {onnx} from 'onnx-proto';
|
||||
|
||||
import {onnxruntime} from './ortSchema/ort_generated';
|
||||
|
||||
import ortFbs = onnxruntime.experimental.fbs;
|
||||
|
||||
import {ProtoUtil, ShapeUtil} from './util';
|
||||
|
||||
export let globalId = 0;
|
||||
|
||||
export declare namespace Tensor {
|
||||
export interface DataTypeMap {
|
||||
bool: Uint8Array;
|
||||
|
@ -31,16 +36,13 @@ export declare namespace Tensor {
|
|||
export type FloatType = Tensor.DataTypeMap['float32']|Tensor.DataTypeMap['float64'];
|
||||
export type NumberType = BooleanType|IntegerType|FloatType;
|
||||
|
||||
export interface Id {
|
||||
// this field helps typescript to perform type check, comparing to use `Id` as an alias of object.
|
||||
_tensorDataId_unused?: never;
|
||||
}
|
||||
export type Id = Guid;
|
||||
}
|
||||
|
||||
type TensorData = Tensor.DataTypeMap[Tensor.DataType];
|
||||
|
||||
type DataProvider = (id: Tensor.Id) => TensorData;
|
||||
type AsyncDataProvider = (id: Tensor.Id) => Promise<TensorData>;
|
||||
type DataProvider = (id: Guid) => TensorData;
|
||||
type AsyncDataProvider = (id: Guid) => Promise<TensorData>;
|
||||
|
||||
export class Tensor {
|
||||
/**
|
||||
|
@ -169,7 +171,7 @@ export class Tensor {
|
|||
/**
|
||||
* get the data ID that used to map to a tensor data
|
||||
*/
|
||||
public readonly dataId: Tensor.Id = {}) {
|
||||
public readonly dataId: Guid = Guid.create()) {
|
||||
this.size = ShapeUtil.validateDimsAndCalcSize(dims);
|
||||
const size = this.size;
|
||||
const empty = (dataProvider === undefined && asyncDataProvider === undefined && cache === undefined);
|
||||
|
|
|
@ -788,6 +788,16 @@
|
|||
"integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==",
|
||||
"dev": true
|
||||
},
|
||||
"bindings": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
|
||||
"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"file-uri-to-path": "1.0.0"
|
||||
}
|
||||
},
|
||||
"bl": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-4.0.3.tgz",
|
||||
|
@ -2469,6 +2479,13 @@
|
|||
"integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==",
|
||||
"dev": true
|
||||
},
|
||||
"file-uri-to-path": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
|
||||
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"filename-reserved-regex": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-2.0.0.tgz",
|
||||
|
@ -3076,6 +3093,12 @@
|
|||
"integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==",
|
||||
"dev": true
|
||||
},
|
||||
"guid-typescript": {
|
||||
"version": "1.0.9",
|
||||
"resolved": "https://registry.npmjs.org/guid-typescript/-/guid-typescript-1.0.9.tgz",
|
||||
"integrity": "sha512-Y8T4vYhEfwJOTbouREvG+3XDsjr8E3kIr7uf+JZ0BYloFsttiHU0WfvANVsR7TxNUJa/WpCnw/Ino/p+DeBhBQ==",
|
||||
"dev": true
|
||||
},
|
||||
"hard-source-webpack-plugin": {
|
||||
"version": "0.13.1",
|
||||
"resolved": "https://registry.npmjs.org/hard-source-webpack-plugin/-/hard-source-webpack-plugin-0.13.1.tgz",
|
||||
|
@ -4766,6 +4789,13 @@
|
|||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||
"dev": true
|
||||
},
|
||||
"nan": {
|
||||
"version": "2.14.2",
|
||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz",
|
||||
"integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"nanomatch": {
|
||||
"version": "1.2.13",
|
||||
"resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
|
||||
|
@ -7265,7 +7295,11 @@
|
|||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
|
||||
"integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"bindings": "^1.5.0",
|
||||
"nan": "^2.12.1"
|
||||
}
|
||||
},
|
||||
"glob-parent": {
|
||||
"version": "3.1.0",
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
"electron": "^9.2.0",
|
||||
"fs-extra": "^9.0.1",
|
||||
"globby": "^11.0.1",
|
||||
"guid-typescript": "^1.0.9",
|
||||
"hard-source-webpack-plugin": "^0.13.1",
|
||||
"husky": "^4.2.5",
|
||||
"karma": "^5.1.1",
|
||||
|
|
|
@ -146,7 +146,7 @@ describe('#UnitTest# - unpack - Tensor unpack', () => {
|
|||
texture: webglTexture!
|
||||
};
|
||||
|
||||
webglInferenceHandler.setTextureData(inputTensor.dataId, textureData);
|
||||
webglInferenceHandler.setTextureData(inputTensor.dataId, textureData, true);
|
||||
|
||||
// compile shader code
|
||||
const programInfo = op.createProgramInfo(inferenceHandler! as WebGLInferenceHandler, [inputTensor]);
|
||||
|
|
Загрузка…
Ссылка в новой задаче