chore: update node_modules with new binary files and dependencies
- Add new binary files for nodemon, onnxruntime-web, and xenova/transformers - Update various JavaScript and TypeScript files in node_modules - Remove unused files and dependencies - Add new test fixtures and documentation files
This commit is contained in:
68
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/batch-normalization.js
generated
vendored
Normal file
68
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/batch-normalization.js
generated
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.parseBatchNormalizationAttributes = exports.batchNormalization = void 0;
|
||||
const attribute_with_cache_key_1 = require("../../../attribute-with-cache-key");
|
||||
const glsl_source_1 = require("../glsl-source");
|
||||
const types_1 = require("../types");
|
||||
const batchNormalizationProgramMetadata = {
|
||||
name: 'BatchNormalization',
|
||||
inputNames: ['A', 'Scale', 'B', 'Mean', 'Variance'],
|
||||
inputTypes: [types_1.TextureType.unpacked, types_1.TextureType.unpacked, types_1.TextureType.unpacked, types_1.TextureType.unpacked, types_1.TextureType.unpacked]
|
||||
};
|
||||
const batchNormalization = (inferenceHandler, inputs, attributes) => {
|
||||
validateInputs(inputs);
|
||||
const output = inferenceHandler.run(Object.assign(Object.assign({}, batchNormalizationProgramMetadata), { cacheHint: attributes.cacheKey, get: () => createBatchNormalizationProgramInfo(inferenceHandler, inputs, attributes) }), inputs);
|
||||
return [output];
|
||||
};
|
||||
exports.batchNormalization = batchNormalization;
|
||||
const parseBatchNormalizationAttributes = (node) => {
|
||||
const epsilon = node.attributes.getFloat('epsilon', 1e-5);
|
||||
const momentum = node.attributes.getFloat('momentum', 0.9);
|
||||
const spatial = node.attributes.getInt('spatial', 1);
|
||||
return (0, attribute_with_cache_key_1.createAttributeWithCacheKey)({ epsilon, momentum, spatial });
|
||||
};
|
||||
exports.parseBatchNormalizationAttributes = parseBatchNormalizationAttributes;
|
||||
const createBatchNormalizationProgramInfo = (inferenceHandler, inputs, attributes) => {
|
||||
const glsl = (0, glsl_source_1.getGlsl)(inferenceHandler.session.backend.glContext.version);
|
||||
const rank = inputs[0].dims.length;
|
||||
const [scaleWidth, scaleHeight] = inferenceHandler.calculateTextureWidthAndHeight(inputs[1].dims, types_1.TextureType.unpacked);
|
||||
const shaderSource = `
|
||||
float process(int[${rank}] indices) {
|
||||
vec2 position = offsetToCoords(indices[1], ${scaleWidth}, ${scaleHeight});
|
||||
float scale = getColorAsFloat(${glsl.texture2D}(Scale, position));
|
||||
float mean = getColorAsFloat(${glsl.texture2D}(Mean, position));
|
||||
float variance = getColorAsFloat(${glsl.texture2D}(Variance, position));
|
||||
float b = getColorAsFloat(${glsl.texture2D}(B, position));
|
||||
|
||||
return scale * ( (_A(indices) - mean) / sqrt(variance + float(${attributes.epsilon})) ) + b;
|
||||
}`;
|
||||
return Object.assign(Object.assign({}, batchNormalizationProgramMetadata), { output: { dims: inputs[0].dims, type: inputs[0].type, textureType: types_1.TextureType.unpacked }, shaderSource });
|
||||
};
|
||||
const validateInputs = (inputs) => {
|
||||
if (!inputs || inputs.length !== 5) {
|
||||
throw new Error('BatchNormalization requires 5 inputs.');
|
||||
}
|
||||
const X = inputs[0];
|
||||
const scale = inputs[1];
|
||||
const B = inputs[2];
|
||||
const mean = inputs[3];
|
||||
const var_ = inputs[4];
|
||||
// input should atleast have three dimensions - N,C,dim1,...,dimn
|
||||
// other inputs can have only one dimensions
|
||||
if (X.dims.length < 3 || scale.dims.length !== 1 || B.dims.length !== 1 || mean.dims.length !== 1 ||
|
||||
var_.dims.length !== 1) {
|
||||
throw new Error('invalid input shape.');
|
||||
}
|
||||
if (scale.dims[0] !== X.dims[1] || B.dims[0] !== X.dims[1] || mean.dims[0] !== X.dims[1] ||
|
||||
var_.dims[0] !== X.dims[1]) {
|
||||
throw new Error('invalid input shape.');
|
||||
}
|
||||
if ((X.type !== 'float32' && X.type !== 'float64') || (scale.type !== 'float32' && scale.type !== 'float64') ||
|
||||
(B.type !== 'float32' && B.type !== 'float64') || (mean.type !== 'float32' && mean.type !== 'float64') ||
|
||||
(var_.type !== 'float32' && var_.type !== 'float64')) {
|
||||
throw new Error('invalid input tensor types.');
|
||||
}
|
||||
};
|
||||
//# sourceMappingURL=batch-normalization.js.map
|
||||
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/batch-normalization.js.map
generated
vendored
Normal file
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/batch-normalization.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"batch-normalization.js","sourceRoot":"","sources":["batch-normalization.ts"],"names":[],"mappings":"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"}
|
||||
96
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/batch-normalization.ts
generated
vendored
Normal file
96
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/batch-normalization.ts
generated
vendored
Normal file
@@ -0,0 +1,96 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../../../attribute-with-cache-key';
|
||||
import {Graph} from '../../../graph';
|
||||
import {OperatorImplementation, OperatorInitialization} from '../../../operators';
|
||||
import {Tensor} from '../../../tensor';
|
||||
import {getGlsl} from '../glsl-source';
|
||||
import {WebGLInferenceHandler} from '../inference-handler';
|
||||
import {ProgramInfo, TextureType} from '../types';
|
||||
|
||||
export interface BatchNormalizationAttributes extends AttributeWithCacheKey {
|
||||
epsilon: number;
|
||||
momentum: number;
|
||||
spatial: number;
|
||||
}
|
||||
|
||||
const batchNormalizationProgramMetadata = {
|
||||
name: 'BatchNormalization',
|
||||
inputNames: ['A', 'Scale', 'B', 'Mean', 'Variance'],
|
||||
inputTypes:
|
||||
[TextureType.unpacked, TextureType.unpacked, TextureType.unpacked, TextureType.unpacked, TextureType.unpacked]
|
||||
};
|
||||
|
||||
export const batchNormalization: OperatorImplementation<BatchNormalizationAttributes> =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: BatchNormalizationAttributes): Tensor[] => {
|
||||
validateInputs(inputs);
|
||||
const output = inferenceHandler.run(
|
||||
{
|
||||
...batchNormalizationProgramMetadata,
|
||||
cacheHint: attributes.cacheKey,
|
||||
get: () => createBatchNormalizationProgramInfo(inferenceHandler, inputs, attributes)
|
||||
},
|
||||
inputs);
|
||||
return [output];
|
||||
};
|
||||
|
||||
export const parseBatchNormalizationAttributes: OperatorInitialization<BatchNormalizationAttributes> =
|
||||
(node: Graph.Node): BatchNormalizationAttributes => {
|
||||
const epsilon = node.attributes.getFloat('epsilon', 1e-5);
|
||||
const momentum = node.attributes.getFloat('momentum', 0.9);
|
||||
const spatial = node.attributes.getInt('spatial', 1);
|
||||
return createAttributeWithCacheKey({epsilon, momentum, spatial});
|
||||
};
|
||||
|
||||
const createBatchNormalizationProgramInfo =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: BatchNormalizationAttributes):
|
||||
ProgramInfo => {
|
||||
const glsl = getGlsl(inferenceHandler.session.backend.glContext.version);
|
||||
const rank = inputs[0].dims.length;
|
||||
const [scaleWidth, scaleHeight] =
|
||||
inferenceHandler.calculateTextureWidthAndHeight(inputs[1].dims, TextureType.unpacked);
|
||||
const shaderSource = `
|
||||
float process(int[${rank}] indices) {
|
||||
vec2 position = offsetToCoords(indices[1], ${scaleWidth}, ${scaleHeight});
|
||||
float scale = getColorAsFloat(${glsl.texture2D}(Scale, position));
|
||||
float mean = getColorAsFloat(${glsl.texture2D}(Mean, position));
|
||||
float variance = getColorAsFloat(${glsl.texture2D}(Variance, position));
|
||||
float b = getColorAsFloat(${glsl.texture2D}(B, position));
|
||||
|
||||
return scale * ( (_A(indices) - mean) / sqrt(variance + float(${attributes.epsilon})) ) + b;
|
||||
}`;
|
||||
return {
|
||||
...batchNormalizationProgramMetadata,
|
||||
output: {dims: inputs[0].dims, type: inputs[0].type, textureType: TextureType.unpacked},
|
||||
shaderSource
|
||||
};
|
||||
};
|
||||
|
||||
const validateInputs = (inputs: Tensor[]): void => {
|
||||
if (!inputs || inputs.length !== 5) {
|
||||
throw new Error('BatchNormalization requires 5 inputs.');
|
||||
}
|
||||
|
||||
const X = inputs[0];
|
||||
const scale = inputs[1];
|
||||
const B = inputs[2];
|
||||
const mean = inputs[3];
|
||||
const var_ = inputs[4];
|
||||
|
||||
// input should atleast have three dimensions - N,C,dim1,...,dimn
|
||||
// other inputs can have only one dimensions
|
||||
if (X.dims.length < 3 || scale.dims.length !== 1 || B.dims.length !== 1 || mean.dims.length !== 1 ||
|
||||
var_.dims.length !== 1) {
|
||||
throw new Error('invalid input shape.');
|
||||
}
|
||||
if (scale.dims[0] !== X.dims[1] || B.dims[0] !== X.dims[1] || mean.dims[0] !== X.dims[1] ||
|
||||
var_.dims[0] !== X.dims[1]) {
|
||||
throw new Error('invalid input shape.');
|
||||
}
|
||||
if ((X.type !== 'float32' && X.type !== 'float64') || (scale.type !== 'float32' && scale.type !== 'float64') ||
|
||||
(B.type !== 'float32' && B.type !== 'float64') || (mean.type !== 'float32' && mean.type !== 'float64') ||
|
||||
(var_.type !== 'float32' && var_.type !== 'float64')) {
|
||||
throw new Error('invalid input tensor types.');
|
||||
}
|
||||
};
|
||||
291
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/binary-op.js
generated
vendored
Normal file
291
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/binary-op.js
generated
vendored
Normal file
@@ -0,0 +1,291 @@
|
||||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.xor = exports.sub = exports.pRelu = exports.pow = exports.or = exports.mul = exports.less = exports.greater = exports.equal = exports.div = exports.and = exports.add = exports.glslPRelu = exports.glslPow = exports.glslXor = exports.glslOr = exports.glslAnd = exports.glslLess = exports.glslGreater = exports.glslEqual = exports.glslSub = exports.glslMul = exports.glslDiv = exports.glslAdd = void 0;
|
||||
const util_1 = require("../../../util");
|
||||
const glsl_definitions_1 = require("../glsl-definitions");
|
||||
const glsl_source_1 = require("../glsl-source");
|
||||
const types_1 = require("../types");
|
||||
function glslAdd() {
|
||||
const name = 'add_';
|
||||
const body = `
|
||||
float ${name}(float a, float b) {
|
||||
return a + b;
|
||||
}
|
||||
vec4 ${name}(vec4 v1, vec4 v2) {
|
||||
return v1 + v2;
|
||||
}
|
||||
`;
|
||||
return { body, name, type: glsl_definitions_1.FunctionType.ValueBased };
|
||||
}
|
||||
exports.glslAdd = glslAdd;
|
||||
function glslDiv() {
|
||||
const name = 'div_';
|
||||
const body = `
|
||||
float ${name}(float a, float b) {
|
||||
return a / b;
|
||||
}
|
||||
vec4 ${name}(vec4 v1, vec4 v2) {
|
||||
return v1 / v2;
|
||||
}
|
||||
`;
|
||||
return { body, name, type: glsl_definitions_1.FunctionType.ValueBased };
|
||||
}
|
||||
exports.glslDiv = glslDiv;
|
||||
function glslMul() {
|
||||
const name = 'mul_';
|
||||
const body = `
|
||||
float ${name}(float a, float b) {
|
||||
return a * b;
|
||||
}
|
||||
vec4 ${name}(vec4 v1, vec4 v2) {
|
||||
return v1 * v2;
|
||||
}
|
||||
`;
|
||||
return { body, name, type: glsl_definitions_1.FunctionType.ValueBased };
|
||||
}
|
||||
exports.glslMul = glslMul;
|
||||
function glslSub() {
|
||||
const name = 'sub_';
|
||||
const body = `
|
||||
float ${name}(float a, float b) {
|
||||
return a - b;
|
||||
}
|
||||
vec4 ${name}(vec4 v1, vec4 v2) {
|
||||
return v1 - v2;
|
||||
}
|
||||
`;
|
||||
return { body, name, type: glsl_definitions_1.FunctionType.ValueBased };
|
||||
}
|
||||
exports.glslSub = glslSub;
|
||||
function glslEqual() {
|
||||
const name = 'equal_';
|
||||
const body = `
|
||||
float ${name}(float a, float b) {
|
||||
return float(a == b);
|
||||
}
|
||||
vec4 ${name}(vec4 v1, vec4 v2) {
|
||||
return vec4(equal(v1, v2));
|
||||
}
|
||||
`;
|
||||
return { body, name, type: glsl_definitions_1.FunctionType.ValueBased };
|
||||
}
|
||||
exports.glslEqual = glslEqual;
|
||||
function glslGreater() {
|
||||
const name = 'greater_';
|
||||
const body = `
|
||||
float ${name}(float a, float b) {
|
||||
return float(a > b);
|
||||
}
|
||||
vec4 ${name}(vec4 v1, vec4 v2) {
|
||||
return vec4( v1.r > v2.r ,
|
||||
v1.g > v2.g,
|
||||
v1.b > v2.b,
|
||||
v1.a > v2.a );
|
||||
}
|
||||
`;
|
||||
return { body, name, type: glsl_definitions_1.FunctionType.ValueBased };
|
||||
}
|
||||
exports.glslGreater = glslGreater;
|
||||
function glslLess() {
|
||||
const name = 'less_';
|
||||
const body = `
|
||||
float ${name}(float a, float b) {
|
||||
return float(a < b);
|
||||
}
|
||||
vec4 ${name}(vec4 v1, vec4 v2) {
|
||||
return vec4( v1.r < v2.r ,
|
||||
v1.g < v2.g,
|
||||
v1.b < v2.b,
|
||||
v1.a < v2.a );
|
||||
}
|
||||
`;
|
||||
return { body, name, type: glsl_definitions_1.FunctionType.ValueBased };
|
||||
}
|
||||
exports.glslLess = glslLess;
|
||||
function glslAnd() {
|
||||
const name = 'and_';
|
||||
const body = `
|
||||
float ${name}(float a, float b) {
|
||||
return float( bool(a) && bool(b) );
|
||||
}
|
||||
vec4 ${name}(vec4 v1, vec4 v2) {
|
||||
bvec4 b1 = bvec4(v1);
|
||||
bvec4 b2 = bvec4(v2);
|
||||
return vec4( b1.r && b2.r ,
|
||||
b1.g && b2.g,
|
||||
b1.b && b2.b,
|
||||
b1.a && b2.a );
|
||||
}
|
||||
`;
|
||||
return { body, name, type: glsl_definitions_1.FunctionType.ValueBased };
|
||||
}
|
||||
exports.glslAnd = glslAnd;
|
||||
function glslOr() {
|
||||
const name = 'or_';
|
||||
const body = `
|
||||
float ${name}(float a, float b) {
|
||||
return float( bool(a) || bool(b) );
|
||||
}
|
||||
vec4 ${name}(vec4 v1, vec4 v2) {
|
||||
bvec4 b1 = bvec4(v1);
|
||||
bvec4 b2 = bvec4(v2);
|
||||
return vec4( b1.r || b2.r ,
|
||||
b1.g || b2.g,
|
||||
b1.b || b2.b,
|
||||
b1.a || b2.a );
|
||||
}
|
||||
`;
|
||||
return { body, name, type: glsl_definitions_1.FunctionType.ValueBased };
|
||||
}
|
||||
exports.glslOr = glslOr;
|
||||
function glslXor() {
|
||||
const name = 'xor_';
|
||||
const body = `
|
||||
float ${name}(float a, float b) {
|
||||
return float( bool(a) ^^ bool(b) );
|
||||
}
|
||||
vec4 ${name}(vec4 v1, vec4 v2) {
|
||||
bvec4 b1 = bvec4(v1);
|
||||
bvec4 b2 = bvec4(v2);
|
||||
return vec4( b1.r ^^ b2.r ,
|
||||
b1.g ^^ b2.g,
|
||||
b1.b ^^ b2.b,
|
||||
b1.a ^^ b2.a );
|
||||
}
|
||||
`;
|
||||
return { body, name, type: glsl_definitions_1.FunctionType.ValueBased };
|
||||
}
|
||||
exports.glslXor = glslXor;
|
||||
function glslPow() {
|
||||
return glslBuiltinBinary('pow');
|
||||
}
|
||||
exports.glslPow = glslPow;
|
||||
function glslPRelu() {
|
||||
const name = 'prelu_';
|
||||
const body = `
|
||||
float ${name}(float a, float b) {
|
||||
return a < 0.0 ? a * b: a;
|
||||
}
|
||||
vec4 ${name}(vec4 v1, vec4 v2) {
|
||||
return vec4(
|
||||
v1.r < 0.0 ? v1.r * v2.r: v1.r,
|
||||
v1.g < 0.0 ? v1.g * v2.g: v1.g,
|
||||
v1.b < 0.0 ? v1.b * v2.b: v1.b,
|
||||
v1.a < 0.0 ? v1.a * v2.a: v1.a
|
||||
);
|
||||
}
|
||||
`;
|
||||
return { body, name, type: glsl_definitions_1.FunctionType.ValueBased };
|
||||
}
|
||||
exports.glslPRelu = glslPRelu;
|
||||
function glslBuiltinBinary(fname) {
|
||||
const name = `${fname}_`;
|
||||
const body = `
|
||||
float ${name}(float a, float b) {
|
||||
return ${fname}(a, b);
|
||||
}
|
||||
vec4 ${name}(vec4 v1, vec4 v2) {
|
||||
return ${fname}(v1, v2);
|
||||
}
|
||||
`;
|
||||
return { body, name, type: glsl_definitions_1.FunctionType.ValueBased };
|
||||
}
|
||||
const createBinaryProgramInfoLoader = (handler, inputs, glslFunc, outputTensorType = inputs[0].type, cacheKey) => {
|
||||
const textureType = handler.session.pack ? types_1.TextureType.packed : types_1.TextureType.unpacked;
|
||||
return {
|
||||
name: glslFunc.name,
|
||||
inputNames: ['A', 'B'],
|
||||
inputTypes: [textureType, textureType],
|
||||
cacheHint: cacheKey,
|
||||
get: () => createBinaryProgramInfo(handler, inputs, glslFunc, outputTensorType)
|
||||
};
|
||||
};
|
||||
const createBinaryProgramInfo = (handler, inputs, glslFunc, outputTensorType = inputs[0].type) => {
|
||||
const textureType = handler.session.pack ? types_1.TextureType.packed : types_1.TextureType.unpacked;
|
||||
const isBroadcast = !util_1.ShapeUtil.areEqual(inputs[0].dims, inputs[1].dims);
|
||||
let outputShape = inputs[0].dims;
|
||||
const usePackedTexture = handler.session.pack;
|
||||
if (isBroadcast) {
|
||||
const calculatedShape = util_1.BroadcastUtil.calcShape(inputs[0].dims, inputs[1].dims, false);
|
||||
if (!calculatedShape) {
|
||||
throw new Error('Can\'t perform binary op on the given tensors');
|
||||
}
|
||||
outputShape = calculatedShape;
|
||||
const outputRank = outputShape.length;
|
||||
const aRank = inputs[0].dims.length !== 0 ? inputs[0].dims.length : 1;
|
||||
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;';
|
||||
const glsl = (0, glsl_source_1.getGlsl)(handler.session.backend.glContext.version);
|
||||
const shaderSource = usePackedTexture ? `
|
||||
${glslFunc.body}
|
||||
void main() {
|
||||
vec4 a = getAAtOutCoords();
|
||||
vec4 b = getBAtOutCoords();
|
||||
vec4 result = ${glslFunc.name}(a, b);
|
||||
${glsl.output} = result;
|
||||
}` :
|
||||
`
|
||||
${glslFunc.body}
|
||||
float process(int indices[${outputRank}]) {
|
||||
int aindices[${aRank}];
|
||||
int bindices[${bRank}];
|
||||
${aBcast}
|
||||
${bBcast}
|
||||
return ${glslFunc.name}(_A(aindices), _B(bindices));
|
||||
}`;
|
||||
return {
|
||||
name: glslFunc.name,
|
||||
inputNames: ['A', 'B'],
|
||||
inputTypes: [textureType, textureType],
|
||||
output: { dims: outputShape, type: outputTensorType, textureType },
|
||||
shaderSource,
|
||||
hasMain: usePackedTexture
|
||||
};
|
||||
}
|
||||
const glsl = (0, glsl_source_1.getGlsl)(handler.session.backend.glContext.version);
|
||||
const shaderSource = `
|
||||
${glslFunc.body}
|
||||
void main() {
|
||||
vec4 v1 = ${glsl.texture2D}(A, TexCoords);
|
||||
vec4 v2 = ${glsl.texture2D}(B, TexCoords);
|
||||
vec4 result = ${glslFunc.name}(v1, v2);
|
||||
${glsl.output} = result;
|
||||
}
|
||||
`;
|
||||
return {
|
||||
name: glslFunc.name,
|
||||
inputNames: ['A', 'B'],
|
||||
inputTypes: [textureType, textureType],
|
||||
output: { dims: inputs[0].dims, type: outputTensorType, textureType },
|
||||
shaderSource,
|
||||
hasMain: true
|
||||
};
|
||||
};
|
||||
const add = (handler, inputs) => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslAdd()), inputs)];
|
||||
exports.add = add;
|
||||
const and = (handler, inputs) => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslAnd(), 'bool'), inputs)];
|
||||
exports.and = and;
|
||||
const div = (handler, inputs) => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslDiv()), inputs)];
|
||||
exports.div = div;
|
||||
const equal = (handler, inputs) => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslEqual(), 'bool'), inputs)];
|
||||
exports.equal = equal;
|
||||
const greater = (handler, inputs) => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslGreater(), 'bool'), inputs)];
|
||||
exports.greater = greater;
|
||||
const less = (handler, inputs) => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslLess(), 'bool'), inputs)];
|
||||
exports.less = less;
|
||||
const mul = (handler, inputs) => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslMul()), inputs)];
|
||||
exports.mul = mul;
|
||||
const or = (handler, inputs) => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslOr(), 'bool'), inputs)];
|
||||
exports.or = or;
|
||||
const pow = (handler, inputs) => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslPow()), inputs)];
|
||||
exports.pow = pow;
|
||||
const pRelu = (handler, inputs) => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslPRelu()), inputs)];
|
||||
exports.pRelu = pRelu;
|
||||
const sub = (handler, inputs) => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslSub()), inputs)];
|
||||
exports.sub = sub;
|
||||
const xor = (handler, inputs) => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslXor(), 'bool'), inputs)];
|
||||
exports.xor = xor;
|
||||
//# sourceMappingURL=binary-op.js.map
|
||||
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/binary-op.js.map
generated
vendored
Normal file
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/binary-op.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
303
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/binary-op.ts
generated
vendored
Normal file
303
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/binary-op.ts
generated
vendored
Normal file
@@ -0,0 +1,303 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import {Tensor} from '../../../tensor';
|
||||
import {BroadcastUtil, ShapeUtil} from '../../../util';
|
||||
import {FunctionType, GlslValueFunction} from '../glsl-definitions';
|
||||
import {getGlsl} from '../glsl-source';
|
||||
import {WebGLInferenceHandler} from '../inference-handler';
|
||||
import {ProgramInfo, ProgramInfoLoader, TextureType} from '../types';
|
||||
|
||||
export function glslAdd(): GlslValueFunction {
|
||||
const name = 'add_';
|
||||
const body = `
|
||||
float ${name}(float a, float b) {
|
||||
return a + b;
|
||||
}
|
||||
vec4 ${name}(vec4 v1, vec4 v2) {
|
||||
return v1 + v2;
|
||||
}
|
||||
`;
|
||||
return {body, name, type: FunctionType.ValueBased};
|
||||
}
|
||||
export function glslDiv(): GlslValueFunction {
|
||||
const name = 'div_';
|
||||
const body = `
|
||||
float ${name}(float a, float b) {
|
||||
return a / b;
|
||||
}
|
||||
vec4 ${name}(vec4 v1, vec4 v2) {
|
||||
return v1 / v2;
|
||||
}
|
||||
`;
|
||||
return {body, name, type: FunctionType.ValueBased};
|
||||
}
|
||||
export function glslMul(): GlslValueFunction {
|
||||
const name = 'mul_';
|
||||
const body = `
|
||||
float ${name}(float a, float b) {
|
||||
return a * b;
|
||||
}
|
||||
vec4 ${name}(vec4 v1, vec4 v2) {
|
||||
return v1 * v2;
|
||||
}
|
||||
`;
|
||||
return {body, name, type: FunctionType.ValueBased};
|
||||
}
|
||||
export function glslSub(): GlslValueFunction {
|
||||
const name = 'sub_';
|
||||
const body = `
|
||||
float ${name}(float a, float b) {
|
||||
return a - b;
|
||||
}
|
||||
vec4 ${name}(vec4 v1, vec4 v2) {
|
||||
return v1 - v2;
|
||||
}
|
||||
`;
|
||||
return {body, name, type: FunctionType.ValueBased};
|
||||
}
|
||||
export function glslEqual(): GlslValueFunction {
|
||||
const name = 'equal_';
|
||||
const body = `
|
||||
float ${name}(float a, float b) {
|
||||
return float(a == b);
|
||||
}
|
||||
vec4 ${name}(vec4 v1, vec4 v2) {
|
||||
return vec4(equal(v1, v2));
|
||||
}
|
||||
`;
|
||||
return {body, name, type: FunctionType.ValueBased};
|
||||
}
|
||||
export function glslGreater(): GlslValueFunction {
|
||||
const name = 'greater_';
|
||||
const body = `
|
||||
float ${name}(float a, float b) {
|
||||
return float(a > b);
|
||||
}
|
||||
vec4 ${name}(vec4 v1, vec4 v2) {
|
||||
return vec4( v1.r > v2.r ,
|
||||
v1.g > v2.g,
|
||||
v1.b > v2.b,
|
||||
v1.a > v2.a );
|
||||
}
|
||||
`;
|
||||
return {body, name, type: FunctionType.ValueBased};
|
||||
}
|
||||
export function glslLess(): GlslValueFunction {
|
||||
const name = 'less_';
|
||||
const body = `
|
||||
float ${name}(float a, float b) {
|
||||
return float(a < b);
|
||||
}
|
||||
vec4 ${name}(vec4 v1, vec4 v2) {
|
||||
return vec4( v1.r < v2.r ,
|
||||
v1.g < v2.g,
|
||||
v1.b < v2.b,
|
||||
v1.a < v2.a );
|
||||
}
|
||||
`;
|
||||
return {body, name, type: FunctionType.ValueBased};
|
||||
}
|
||||
export function glslAnd(): GlslValueFunction {
|
||||
const name = 'and_';
|
||||
const body = `
|
||||
float ${name}(float a, float b) {
|
||||
return float( bool(a) && bool(b) );
|
||||
}
|
||||
vec4 ${name}(vec4 v1, vec4 v2) {
|
||||
bvec4 b1 = bvec4(v1);
|
||||
bvec4 b2 = bvec4(v2);
|
||||
return vec4( b1.r && b2.r ,
|
||||
b1.g && b2.g,
|
||||
b1.b && b2.b,
|
||||
b1.a && b2.a );
|
||||
}
|
||||
`;
|
||||
return {body, name, type: FunctionType.ValueBased};
|
||||
}
|
||||
export function glslOr(): GlslValueFunction {
|
||||
const name = 'or_';
|
||||
const body = `
|
||||
float ${name}(float a, float b) {
|
||||
return float( bool(a) || bool(b) );
|
||||
}
|
||||
vec4 ${name}(vec4 v1, vec4 v2) {
|
||||
bvec4 b1 = bvec4(v1);
|
||||
bvec4 b2 = bvec4(v2);
|
||||
return vec4( b1.r || b2.r ,
|
||||
b1.g || b2.g,
|
||||
b1.b || b2.b,
|
||||
b1.a || b2.a );
|
||||
}
|
||||
`;
|
||||
return {body, name, type: FunctionType.ValueBased};
|
||||
}
|
||||
export function glslXor(): GlslValueFunction {
|
||||
const name = 'xor_';
|
||||
const body = `
|
||||
float ${name}(float a, float b) {
|
||||
return float( bool(a) ^^ bool(b) );
|
||||
}
|
||||
vec4 ${name}(vec4 v1, vec4 v2) {
|
||||
bvec4 b1 = bvec4(v1);
|
||||
bvec4 b2 = bvec4(v2);
|
||||
return vec4( b1.r ^^ b2.r ,
|
||||
b1.g ^^ b2.g,
|
||||
b1.b ^^ b2.b,
|
||||
b1.a ^^ b2.a );
|
||||
}
|
||||
`;
|
||||
return {body, name, type: FunctionType.ValueBased};
|
||||
}
|
||||
export function glslPow(): GlslValueFunction {
|
||||
return glslBuiltinBinary('pow');
|
||||
}
|
||||
export function glslPRelu(): GlslValueFunction {
|
||||
const name = 'prelu_';
|
||||
const body = `
|
||||
float ${name}(float a, float b) {
|
||||
return a < 0.0 ? a * b: a;
|
||||
}
|
||||
vec4 ${name}(vec4 v1, vec4 v2) {
|
||||
return vec4(
|
||||
v1.r < 0.0 ? v1.r * v2.r: v1.r,
|
||||
v1.g < 0.0 ? v1.g * v2.g: v1.g,
|
||||
v1.b < 0.0 ? v1.b * v2.b: v1.b,
|
||||
v1.a < 0.0 ? v1.a * v2.a: v1.a
|
||||
);
|
||||
}
|
||||
`;
|
||||
return {body, name, type: FunctionType.ValueBased};
|
||||
}
|
||||
|
||||
function glslBuiltinBinary(fname: string): GlslValueFunction {
|
||||
const name = `${fname}_`;
|
||||
const body = `
|
||||
float ${name}(float a, float b) {
|
||||
return ${fname}(a, b);
|
||||
}
|
||||
vec4 ${name}(vec4 v1, vec4 v2) {
|
||||
return ${fname}(v1, v2);
|
||||
}
|
||||
`;
|
||||
return {body, name, type: FunctionType.ValueBased};
|
||||
}
|
||||
|
||||
const createBinaryProgramInfoLoader =
|
||||
(handler: WebGLInferenceHandler, inputs: Tensor[], glslFunc: GlslValueFunction,
|
||||
outputTensorType: Tensor.DataType = inputs[0].type, cacheKey?: string): ProgramInfoLoader => {
|
||||
const textureType = handler.session.pack ? TextureType.packed : TextureType.unpacked;
|
||||
return {
|
||||
name: glslFunc.name,
|
||||
inputNames: ['A', 'B'],
|
||||
inputTypes: [textureType, textureType],
|
||||
cacheHint: cacheKey,
|
||||
get: () => createBinaryProgramInfo(handler, inputs, glslFunc, outputTensorType)
|
||||
};
|
||||
};
|
||||
|
||||
const createBinaryProgramInfo =
|
||||
(handler: WebGLInferenceHandler, inputs: Tensor[], glslFunc: GlslValueFunction,
|
||||
outputTensorType: Tensor.DataType = inputs[0].type): ProgramInfo => {
|
||||
const textureType = handler.session.pack ? TextureType.packed : TextureType.unpacked;
|
||||
const isBroadcast = !ShapeUtil.areEqual(inputs[0].dims, inputs[1].dims);
|
||||
let outputShape = inputs[0].dims;
|
||||
|
||||
const usePackedTexture = handler.session.pack;
|
||||
|
||||
if (isBroadcast) {
|
||||
const calculatedShape = BroadcastUtil.calcShape(inputs[0].dims, inputs[1].dims, false);
|
||||
if (!calculatedShape) {
|
||||
throw new Error('Can\'t perform binary op on the given tensors');
|
||||
}
|
||||
outputShape = calculatedShape;
|
||||
const outputRank = outputShape.length;
|
||||
const aRank = inputs[0].dims.length !== 0 ? inputs[0].dims.length : 1;
|
||||
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;';
|
||||
|
||||
const glsl = getGlsl(handler.session.backend.glContext.version);
|
||||
const shaderSource = usePackedTexture ? `
|
||||
${glslFunc.body}
|
||||
void main() {
|
||||
vec4 a = getAAtOutCoords();
|
||||
vec4 b = getBAtOutCoords();
|
||||
vec4 result = ${glslFunc.name}(a, b);
|
||||
${glsl.output} = result;
|
||||
}` :
|
||||
`
|
||||
${glslFunc.body}
|
||||
float process(int indices[${outputRank}]) {
|
||||
int aindices[${aRank}];
|
||||
int bindices[${bRank}];
|
||||
${aBcast}
|
||||
${bBcast}
|
||||
return ${glslFunc.name}(_A(aindices), _B(bindices));
|
||||
}`;
|
||||
|
||||
return {
|
||||
name: glslFunc.name,
|
||||
inputNames: ['A', 'B'],
|
||||
inputTypes: [textureType, textureType],
|
||||
output: {dims: outputShape, type: outputTensorType, textureType},
|
||||
shaderSource,
|
||||
hasMain: usePackedTexture
|
||||
};
|
||||
}
|
||||
const glsl = getGlsl(handler.session.backend.glContext.version);
|
||||
const shaderSource = `
|
||||
${glslFunc.body}
|
||||
void main() {
|
||||
vec4 v1 = ${glsl.texture2D}(A, TexCoords);
|
||||
vec4 v2 = ${glsl.texture2D}(B, TexCoords);
|
||||
vec4 result = ${glslFunc.name}(v1, v2);
|
||||
${glsl.output} = result;
|
||||
}
|
||||
`;
|
||||
|
||||
return {
|
||||
name: glslFunc.name,
|
||||
inputNames: ['A', 'B'],
|
||||
inputTypes: [textureType, textureType],
|
||||
output: {dims: inputs[0].dims, type: outputTensorType, textureType},
|
||||
shaderSource,
|
||||
hasMain: true
|
||||
};
|
||||
};
|
||||
|
||||
export const add = (handler: WebGLInferenceHandler, inputs: Tensor[]):
|
||||
Tensor[] => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslAdd()), inputs)];
|
||||
|
||||
export const and = (handler: WebGLInferenceHandler, inputs: Tensor[]):
|
||||
Tensor[] => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslAnd(), 'bool'), inputs)];
|
||||
|
||||
export const div = (handler: WebGLInferenceHandler, inputs: Tensor[]):
|
||||
Tensor[] => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslDiv()), inputs)];
|
||||
|
||||
export const equal = (handler: WebGLInferenceHandler, inputs: Tensor[]):
|
||||
Tensor[] => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslEqual(), 'bool'), inputs)];
|
||||
|
||||
export const greater = (handler: WebGLInferenceHandler, inputs: Tensor[]):
|
||||
Tensor[] => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslGreater(), 'bool'), inputs)];
|
||||
|
||||
export const less = (handler: WebGLInferenceHandler, inputs: Tensor[]):
|
||||
Tensor[] => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslLess(), 'bool'), inputs)];
|
||||
|
||||
export const mul = (handler: WebGLInferenceHandler, inputs: Tensor[]):
|
||||
Tensor[] => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslMul()), inputs)];
|
||||
|
||||
export const or = (handler: WebGLInferenceHandler, inputs: Tensor[]):
|
||||
Tensor[] => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslOr(), 'bool'), inputs)];
|
||||
|
||||
export const pow = (handler: WebGLInferenceHandler, inputs: Tensor[]):
|
||||
Tensor[] => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslPow()), inputs)];
|
||||
|
||||
export const pRelu = (handler: WebGLInferenceHandler, inputs: Tensor[]):
|
||||
Tensor[] => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslPRelu()), inputs)];
|
||||
|
||||
export const sub = (handler: WebGLInferenceHandler, inputs: Tensor[]):
|
||||
Tensor[] => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslSub()), inputs)];
|
||||
|
||||
export const xor = (handler: WebGLInferenceHandler, inputs: Tensor[]):
|
||||
Tensor[] => [handler.run(createBinaryProgramInfoLoader(handler, inputs, glslXor(), 'bool'), inputs)];
|
||||
22
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/cast.js
generated
vendored
Normal file
22
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/cast.js
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.parseCastAttributes = exports.cast = void 0;
|
||||
const util_1 = require("../../../util");
|
||||
const cast = (handler, inputs, to) => {
|
||||
validateInputs(inputs);
|
||||
return [handler.cast(inputs[0], to)];
|
||||
};
|
||||
exports.cast = cast;
|
||||
const parseCastAttributes = (node) => util_1.ProtoUtil.tensorDataTypeFromProto(node.attributes.getInt('to'));
|
||||
exports.parseCastAttributes = parseCastAttributes;
|
||||
const validateInputs = (inputs) => {
|
||||
if (!inputs || inputs.length !== 1) {
|
||||
throw new Error('Cast requires 1 input.');
|
||||
}
|
||||
if (inputs[0].type === 'string') {
|
||||
throw new Error('Invalid input type.');
|
||||
}
|
||||
};
|
||||
//# sourceMappingURL=cast.js.map
|
||||
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/cast.js.map
generated
vendored
Normal file
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/cast.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"cast.js","sourceRoot":"","sources":["cast.ts"],"names":[],"mappings":";AAAA,4DAA4D;AAC5D,kCAAkC;;;AAKlC,wCAAwC;AAGjC,MAAM,IAAI,GACb,CAAC,OAA8B,EAAE,MAAgB,EAAE,EAAmB,EAAY,EAAE;IAClF,cAAc,CAAC,MAAM,CAAC,CAAC;IACvB,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;AACvC,CAAC,CAAC;AAJO,QAAA,IAAI,QAIX;AAEC,MAAM,mBAAmB,GAA4C,CAAC,IAAgB,EAAmB,EAAE,CAC9G,gBAAS,CAAC,uBAAuB,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;AADvD,QAAA,mBAAmB,uBACoC;AAEpE,MAAM,cAAc,GAAG,CAAC,MAAgB,EAAQ,EAAE;IAChD,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE;QAClC,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;KAC3C;IAED,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,EAAE;QAC/B,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;KACxC;AACH,CAAC,CAAC"}
|
||||
27
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/cast.ts
generated
vendored
Normal file
27
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/cast.ts
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import {Graph} from '../../../graph';
|
||||
import {OperatorImplementation, OperatorInitialization} from '../../../operators';
|
||||
import {Tensor} from '../../../tensor';
|
||||
import {ProtoUtil} from '../../../util';
|
||||
import {WebGLInferenceHandler} from '../inference-handler';
|
||||
|
||||
export const cast: OperatorImplementation<Tensor.DataType> =
|
||||
(handler: WebGLInferenceHandler, inputs: Tensor[], to: Tensor.DataType): Tensor[] => {
|
||||
validateInputs(inputs);
|
||||
return [handler.cast(inputs[0], to)];
|
||||
};
|
||||
|
||||
export const parseCastAttributes: OperatorInitialization<Tensor.DataType> = (node: Graph.Node): Tensor.DataType =>
|
||||
ProtoUtil.tensorDataTypeFromProto(node.attributes.getInt('to'));
|
||||
|
||||
const validateInputs = (inputs: Tensor[]): void => {
|
||||
if (!inputs || inputs.length !== 1) {
|
||||
throw new Error('Cast requires 1 input.');
|
||||
}
|
||||
|
||||
if (inputs[0].type === 'string') {
|
||||
throw new Error('Invalid input type.');
|
||||
}
|
||||
};
|
||||
125
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/concat-packed.js
generated
vendored
Normal file
125
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/concat-packed.js
generated
vendored
Normal file
@@ -0,0 +1,125 @@
|
||||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createPackedConcatProgramInfoLoader = void 0;
|
||||
const glsl_source_1 = require("../glsl-source");
|
||||
const types_1 = require("../types");
|
||||
const utils_1 = require("../utils");
|
||||
const packing_utils_1 = require("./packing-utils");
|
||||
const createPackedConcatProgramMetadata = (inputCount, cacheHint) => ({
|
||||
name: 'Concat (packed)',
|
||||
inputNames: Array.from({ length: inputCount }, (v, i) => `X${i}`),
|
||||
inputTypes: Array(inputCount).fill(types_1.TextureType.packed),
|
||||
cacheHint
|
||||
});
|
||||
const createPackedConcatProgramInfo = (handler, metadata, inputs, axis) => {
|
||||
const inputShape = inputs[0].dims.slice();
|
||||
if (axis >= inputShape.length || axis < (-1 * inputShape.length)) {
|
||||
throw new Error('axis specified for concat doesn\'t match input dimensionality');
|
||||
}
|
||||
if (axis < 0) {
|
||||
axis = inputShape.length + axis;
|
||||
}
|
||||
// ensure all of the non-concatenated axes match each other
|
||||
// calculate the shape of the output tensor while we do that
|
||||
const outputShape = inputShape.slice(0);
|
||||
for (let i = 1; i < inputs.length; i++) {
|
||||
const dataNShape = inputs[i].dims.slice();
|
||||
for (let axisIndex = 0; axisIndex < inputShape.length; axisIndex++) {
|
||||
// add to the placeholder for computing output shape
|
||||
if (axisIndex === axis) {
|
||||
outputShape[axis] += dataNShape[axisIndex];
|
||||
}
|
||||
// ensure all non-cancatenated axes match each other
|
||||
else if (inputShape[axisIndex] !== dataNShape[axisIndex]) {
|
||||
throw new Error('non concat dimensions must match');
|
||||
}
|
||||
}
|
||||
}
|
||||
const rank = outputShape.length;
|
||||
const coords = (0, packing_utils_1.getChannels)('coords', rank);
|
||||
const dtype = (0, utils_1.getCoordsDataType)(rank);
|
||||
const unpackChannel = (0, packing_utils_1.unpackFromChannel)();
|
||||
const shapes = inputs.map(i => i.dims);
|
||||
const channels = (0, utils_1.getGlChannels)(rank);
|
||||
const offsets = new Array(shapes.length - 1);
|
||||
offsets[0] = shapes[0][axis];
|
||||
for (let i = 1; i < offsets.length; i++) {
|
||||
offsets[i] = offsets[i - 1] + shapes[i][axis];
|
||||
}
|
||||
const channel = channels[axis];
|
||||
const lastChannels = channels.slice(-2);
|
||||
const allChannels = channels.join();
|
||||
let getValueSnippet = `if (${channel} < ${offsets[0]}) {
|
||||
return getChannel(
|
||||
getX0(${allChannels}), vec2(${lastChannels.join()}));
|
||||
}`;
|
||||
for (let i = 1; i < offsets.length; i++) {
|
||||
const shift = offsets[i - 1];
|
||||
getValueSnippet += `
|
||||
if (${channel} < ${offsets[i]} && ${channel} >= ${offsets[i - 1]}) {
|
||||
return getChannel(
|
||||
getX${i}(${getShiftedChannelsSnippet(channels, channel, shift)}),
|
||||
vec2(${getShiftedChannelsSnippet(lastChannels, channel, shift)}));
|
||||
}`;
|
||||
}
|
||||
const lastIndex = offsets.length;
|
||||
const shift = offsets[offsets.length - 1];
|
||||
getValueSnippet += `
|
||||
return getChannel(
|
||||
getX${lastIndex}(${getShiftedChannelsSnippet(channels, channel, shift)}),
|
||||
vec2(${getShiftedChannelsSnippet(lastChannels, channel, shift)}));`;
|
||||
const glsl = (0, glsl_source_1.getGlsl)(handler.session.backend.glContext.version);
|
||||
const shaderSource = `
|
||||
${unpackChannel}
|
||||
float getValue(${channels.map(x => 'int ' + x)}) {
|
||||
${getValueSnippet}
|
||||
}
|
||||
|
||||
void main() {
|
||||
${dtype} coords = getOutputCoords();
|
||||
int lastDim = coords.${channels[rank - 1]};
|
||||
coords.${channels[rank - 1]} = coords.${channels[rank - 2]};
|
||||
coords.${channels[rank - 2]} = lastDim;
|
||||
|
||||
vec4 result = vec4(getValue(${coords}), 0., 0., 0.);
|
||||
|
||||
${coords[rank - 1]} = ${coords[rank - 1]} + 1;
|
||||
if (${coords[rank - 1]} < ${outputShape[rank - 1]}) {
|
||||
result.g = getValue(${coords});
|
||||
}
|
||||
|
||||
${coords[rank - 2]} = ${coords[rank - 2]} + 1;
|
||||
if (${coords[rank - 2]} < ${outputShape[rank - 2]}) {
|
||||
result.a = getValue(${coords});
|
||||
}
|
||||
|
||||
${coords[rank - 1]} = ${coords[rank - 1]} - 1;
|
||||
if (${coords[rank - 2]} < ${outputShape[rank - 2]} &&
|
||||
${coords[rank - 1]} < ${outputShape[rank - 1]}) {
|
||||
result.b = getValue(${coords});
|
||||
}
|
||||
${glsl.output} = result;
|
||||
}
|
||||
`;
|
||||
return Object.assign(Object.assign({}, metadata), { output: { dims: outputShape, type: inputs[0].type, textureType: types_1.TextureType.packed }, shaderSource, hasMain: true });
|
||||
};
|
||||
const createPackedConcatProgramInfoLoader = (handler, inputs, attributes) => {
|
||||
const metadata = createPackedConcatProgramMetadata(inputs.length, attributes.cacheKey);
|
||||
return Object.assign(Object.assign({}, metadata), { get: () => createPackedConcatProgramInfo(handler, metadata, inputs, attributes.axis) });
|
||||
};
|
||||
exports.createPackedConcatProgramInfoLoader = createPackedConcatProgramInfoLoader;
|
||||
const getShiftedChannelsSnippet = (channels, channel, shift) => {
|
||||
const channelIdx = channels.indexOf(channel);
|
||||
const res = channels.map((c, idx) => {
|
||||
if (idx === channelIdx) {
|
||||
return `${c} - ${shift}`;
|
||||
}
|
||||
else {
|
||||
return c;
|
||||
}
|
||||
});
|
||||
return res.join();
|
||||
};
|
||||
//# sourceMappingURL=concat-packed.js.map
|
||||
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/concat-packed.js.map
generated
vendored
Normal file
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/concat-packed.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"concat-packed.js","sourceRoot":"","sources":["concat-packed.ts"],"names":[],"mappings":"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"}
|
||||
143
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/concat-packed.ts
generated
vendored
Normal file
143
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/concat-packed.ts
generated
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import {Tensor} from '../../../tensor';
|
||||
import {getGlsl} from '../glsl-source';
|
||||
import {WebGLInferenceHandler} from '../inference-handler';
|
||||
import {ProgramInfo, ProgramInfoLoader, ProgramMetadata, TextureType} from '../types';
|
||||
import {getCoordsDataType, getGlChannels} from '../utils';
|
||||
|
||||
import {ConcatAttributes} from './concat';
|
||||
import {getChannels, unpackFromChannel} from './packing-utils';
|
||||
|
||||
const createPackedConcatProgramMetadata = (inputCount: number, cacheHint: string) => ({
|
||||
name: 'Concat (packed)',
|
||||
inputNames: Array.from({length: inputCount}, (v, i) => `X${i}`),
|
||||
inputTypes: Array(inputCount).fill(TextureType.packed),
|
||||
cacheHint
|
||||
});
|
||||
|
||||
const createPackedConcatProgramInfo =
|
||||
(handler: WebGLInferenceHandler, metadata: ProgramMetadata, inputs: Tensor[], axis: number): ProgramInfo => {
|
||||
const inputShape = inputs[0].dims.slice();
|
||||
if (axis >= inputShape.length || axis < (-1 * inputShape.length)) {
|
||||
throw new Error('axis specified for concat doesn\'t match input dimensionality');
|
||||
}
|
||||
if (axis < 0) {
|
||||
axis = inputShape.length + axis;
|
||||
}
|
||||
// ensure all of the non-concatenated axes match each other
|
||||
// calculate the shape of the output tensor while we do that
|
||||
const outputShape = inputShape.slice(0);
|
||||
for (let i = 1; i < inputs.length; i++) {
|
||||
const dataNShape = inputs[i].dims.slice();
|
||||
for (let axisIndex = 0; axisIndex < inputShape.length; axisIndex++) {
|
||||
// add to the placeholder for computing output shape
|
||||
if (axisIndex === axis) {
|
||||
outputShape[axis] += dataNShape[axisIndex];
|
||||
}
|
||||
// ensure all non-cancatenated axes match each other
|
||||
else if (inputShape[axisIndex] !== dataNShape[axisIndex]) {
|
||||
throw new Error('non concat dimensions must match');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const rank = outputShape.length;
|
||||
const coords = getChannels('coords', rank);
|
||||
const dtype = getCoordsDataType(rank);
|
||||
const unpackChannel = unpackFromChannel();
|
||||
|
||||
const shapes = inputs.map(i => i.dims);
|
||||
const channels = getGlChannels(rank);
|
||||
const offsets: number[] = new Array(shapes.length - 1);
|
||||
|
||||
offsets[0] = shapes[0][axis];
|
||||
for (let i = 1; i < offsets.length; i++) {
|
||||
offsets[i] = offsets[i - 1] + shapes[i][axis];
|
||||
}
|
||||
|
||||
const channel = channels[axis];
|
||||
const lastChannels = channels.slice(-2);
|
||||
const allChannels = channels.join();
|
||||
|
||||
let getValueSnippet = `if (${channel} < ${offsets[0]}) {
|
||||
return getChannel(
|
||||
getX0(${allChannels}), vec2(${lastChannels.join()}));
|
||||
}`;
|
||||
for (let i = 1; i < offsets.length; i++) {
|
||||
const shift = offsets[i - 1];
|
||||
getValueSnippet += `
|
||||
if (${channel} < ${offsets[i]} && ${channel} >= ${offsets[i - 1]}) {
|
||||
return getChannel(
|
||||
getX${i}(${getShiftedChannelsSnippet(channels, channel, shift)}),
|
||||
vec2(${getShiftedChannelsSnippet(lastChannels, channel, shift)}));
|
||||
}`;
|
||||
}
|
||||
const lastIndex = offsets.length;
|
||||
const shift = offsets[offsets.length - 1];
|
||||
getValueSnippet += `
|
||||
return getChannel(
|
||||
getX${lastIndex}(${getShiftedChannelsSnippet(channels, channel, shift)}),
|
||||
vec2(${getShiftedChannelsSnippet(lastChannels, channel, shift)}));`;
|
||||
|
||||
const glsl = getGlsl(handler.session.backend.glContext.version);
|
||||
|
||||
const shaderSource = `
|
||||
${unpackChannel}
|
||||
float getValue(${channels.map(x => 'int ' + x)}) {
|
||||
${getValueSnippet}
|
||||
}
|
||||
|
||||
void main() {
|
||||
${dtype} coords = getOutputCoords();
|
||||
int lastDim = coords.${channels[rank - 1]};
|
||||
coords.${channels[rank - 1]} = coords.${channels[rank - 2]};
|
||||
coords.${channels[rank - 2]} = lastDim;
|
||||
|
||||
vec4 result = vec4(getValue(${coords}), 0., 0., 0.);
|
||||
|
||||
${coords[rank - 1]} = ${coords[rank - 1]} + 1;
|
||||
if (${coords[rank - 1]} < ${outputShape[rank - 1]}) {
|
||||
result.g = getValue(${coords});
|
||||
}
|
||||
|
||||
${coords[rank - 2]} = ${coords[rank - 2]} + 1;
|
||||
if (${coords[rank - 2]} < ${outputShape[rank - 2]}) {
|
||||
result.a = getValue(${coords});
|
||||
}
|
||||
|
||||
${coords[rank - 1]} = ${coords[rank - 1]} - 1;
|
||||
if (${coords[rank - 2]} < ${outputShape[rank - 2]} &&
|
||||
${coords[rank - 1]} < ${outputShape[rank - 1]}) {
|
||||
result.b = getValue(${coords});
|
||||
}
|
||||
${glsl.output} = result;
|
||||
}
|
||||
`;
|
||||
|
||||
return {
|
||||
...metadata,
|
||||
output: {dims: outputShape, type: inputs[0].type, textureType: TextureType.packed},
|
||||
shaderSource,
|
||||
hasMain: true,
|
||||
};
|
||||
};
|
||||
|
||||
export const createPackedConcatProgramInfoLoader =
|
||||
(handler: WebGLInferenceHandler, inputs: Tensor[], attributes: ConcatAttributes): ProgramInfoLoader => {
|
||||
const metadata = createPackedConcatProgramMetadata(inputs.length, attributes.cacheKey);
|
||||
return {...metadata, get: () => createPackedConcatProgramInfo(handler, metadata, inputs, attributes.axis)};
|
||||
};
|
||||
|
||||
const getShiftedChannelsSnippet = (channels: string[], channel: string, shift: number): string => {
|
||||
const channelIdx = channels.indexOf(channel);
|
||||
const res = channels.map((c, idx) => {
|
||||
if (idx === channelIdx) {
|
||||
return `${c} - ${shift}`;
|
||||
} else {
|
||||
return c;
|
||||
}
|
||||
});
|
||||
return res.join();
|
||||
};
|
||||
159
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/concat.js
generated
vendored
Normal file
159
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/concat.js
generated
vendored
Normal file
@@ -0,0 +1,159 @@
|
||||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.parseConcatAttributes = exports.concat = void 0;
|
||||
const attribute_with_cache_key_1 = require("../../../attribute-with-cache-key");
|
||||
const types_1 = require("../types");
|
||||
const concat_packed_1 = require("./concat-packed");
|
||||
const concat = (inferenceHandler, inputs, attributes) => {
|
||||
validateInputs(inputs);
|
||||
if (inferenceHandler.session.pack && inputs[0].dims.length > 1) {
|
||||
const output = inferenceHandler.run((0, concat_packed_1.createPackedConcatProgramInfoLoader)(inferenceHandler, inputs, attributes), inputs);
|
||||
return [output];
|
||||
}
|
||||
else {
|
||||
const output = inferenceHandler.run(createUnpackedConcatProgramInfoLoader(inferenceHandler, inputs, attributes), inputs);
|
||||
return [output];
|
||||
}
|
||||
};
|
||||
exports.concat = concat;
|
||||
const createUnpackedConcatProgramMetadata = (inputCount, cacheHint) => ({
|
||||
name: 'Concat',
|
||||
inputNames: Array.from({ length: inputCount }, (v, i) => `X${i}`),
|
||||
inputTypes: Array(inputCount).fill(types_1.TextureType.unpacked),
|
||||
cacheHint
|
||||
});
|
||||
const createUnpackedConcatProgramInfo = (handler, metadata, inputs, axis) => {
|
||||
const inputShape = inputs[0].dims.slice();
|
||||
if (axis >= inputShape.length || axis < (-1 * inputShape.length)) {
|
||||
throw new Error('axis specified for concat doesn\'t match input dimensionality');
|
||||
}
|
||||
if (axis < 0) {
|
||||
axis = inputShape.length + axis;
|
||||
}
|
||||
// ensure all of the non-concatenated axes match each other
|
||||
// calculate the shape of the output tensor while we do that
|
||||
const outputShape = inputShape.slice(0);
|
||||
for (let i = 1; i < inputs.length; i++) {
|
||||
const dataNShape = inputs[i].dims.slice();
|
||||
for (let axisIndex = 0; axisIndex < inputShape.length; axisIndex++) {
|
||||
// add to the placeholder for computing output shape
|
||||
if (axisIndex === axis) {
|
||||
outputShape[axis] += dataNShape[axisIndex];
|
||||
}
|
||||
// ensure all non-cancatenated axes match each other
|
||||
else if (inputShape[axisIndex] !== dataNShape[axisIndex]) {
|
||||
throw new Error('non concat dimensions must match');
|
||||
}
|
||||
}
|
||||
}
|
||||
const rank = outputShape.length;
|
||||
const sizeInConcatAxis = new Array(inputs.length);
|
||||
let previousSum = 0;
|
||||
for (let i = 0; i < sizeInConcatAxis.length; ++i) {
|
||||
previousSum += inputs[i].dims[axis];
|
||||
sizeInConcatAxis[i] = previousSum;
|
||||
}
|
||||
let getTextureIndexWhereDataResidesMethod = '';
|
||||
// in most cases linear search is sufficient, as in most scenarios, only 2 tensors are concatenated
|
||||
if (inputs.length < 5) {
|
||||
getTextureIndexWhereDataResidesMethod = getTextureIndexWhereDataResidesLinearSearch(sizeInConcatAxis);
|
||||
}
|
||||
else {
|
||||
getTextureIndexWhereDataResidesMethod = getTextureIndexWhereDataResidesBinarySearch(sizeInConcatAxis);
|
||||
}
|
||||
const fetchDataFromCorrectTextureMethod = getFetchDataFromCorrectTextureMethod(inputs.length, rank);
|
||||
const getSizeInConcatAxisValueFromIndexMethod = getGetSizeInConcatAxisValueFromIndexMethod(sizeInConcatAxis);
|
||||
const shaderSource = `
|
||||
${fetchDataFromCorrectTextureMethod}
|
||||
${getSizeInConcatAxisValueFromIndexMethod}
|
||||
${getTextureIndexWhereDataResidesMethod}
|
||||
float process(int indices[${rank}]) {
|
||||
int textureIndex = getTextureWhereDataResides (indices[${axis}]);
|
||||
|
||||
if(textureIndex != 0) {
|
||||
indices[${axis}] = indices[${axis}] - int(getSizeInConcatAxisValueFromIndex(textureIndex-int(1)));
|
||||
}
|
||||
|
||||
return fetchDataFromCorrectTexture(textureIndex, indices);
|
||||
}`;
|
||||
return Object.assign(Object.assign({}, metadata), { output: { dims: outputShape, type: inputs[0].type, textureType: types_1.TextureType.unpacked }, shaderSource });
|
||||
};
|
||||
const createUnpackedConcatProgramInfoLoader = (handler, inputs, attributes) => {
|
||||
const metadata = createUnpackedConcatProgramMetadata(inputs.length, attributes.cacheKey);
|
||||
return Object.assign(Object.assign({}, metadata), { get: () => createUnpackedConcatProgramInfo(handler, metadata, inputs, attributes.axis) });
|
||||
};
|
||||
const getTextureIndexWhereDataResidesLinearSearch = (sizeInConcatAxis) => {
|
||||
const searchAxis = sizeInConcatAxis.map((size, i) => `if(index<${size}) {return ${i};}
|
||||
`);
|
||||
return `int getTextureWhereDataResides(int index) {
|
||||
${searchAxis.join('')}
|
||||
}`;
|
||||
};
|
||||
// TODO: Implement BinarySearch in GLSL
|
||||
const getTextureIndexWhereDataResidesBinarySearch = (sizeInConcatAxis) => getTextureIndexWhereDataResidesLinearSearch(sizeInConcatAxis);
|
||||
const getFetchDataFromCorrectTextureMethod = (numberOfTensors, tensorRank) => {
|
||||
const codeLines = [`float fetchDataFromCorrectTexture(int textureIndex, int indices[${tensorRank}]) {`];
|
||||
for (let i = 0; i < numberOfTensors; ++i) {
|
||||
if (i === 0) {
|
||||
codeLines.push('\t' +
|
||||
`if (textureIndex == ${i}) { return _X${i}(indices); }`);
|
||||
}
|
||||
else if (i === numberOfTensors - 1) {
|
||||
codeLines.push('\t' +
|
||||
`else { return _X${i}(indices); }`);
|
||||
}
|
||||
else {
|
||||
codeLines.push('\t' +
|
||||
`else if (textureIndex == ${i}) { return _X${i}(indices); }`);
|
||||
}
|
||||
}
|
||||
codeLines.push('\t' +
|
||||
'}');
|
||||
return codeLines.join('\n');
|
||||
};
|
||||
const getGetSizeInConcatAxisValueFromIndexMethod = (sizeInConcatAxis) => {
|
||||
const codeLines = ['int getSizeInConcatAxisValueFromIndex(int index) {'];
|
||||
for (let i = 0; i < sizeInConcatAxis.length; ++i) {
|
||||
if (i === 0) {
|
||||
codeLines.push('\t' +
|
||||
`if (index == ${i}) { return ${sizeInConcatAxis[i]}; }`);
|
||||
}
|
||||
else if (i === sizeInConcatAxis.length - 1) {
|
||||
codeLines.push('\t' +
|
||||
`else { return ${sizeInConcatAxis[i]}; }`);
|
||||
}
|
||||
else {
|
||||
codeLines.push('\t' +
|
||||
`else if (index == ${i}) { return ${sizeInConcatAxis[i]}; }`);
|
||||
}
|
||||
}
|
||||
codeLines.push('\t' +
|
||||
'}');
|
||||
return codeLines.join('\n');
|
||||
};
|
||||
const parseConcatAttributes = (node) => (0, attribute_with_cache_key_1.createAttributeWithCacheKey)({ axis: node.attributes.getInt('axis') });
|
||||
exports.parseConcatAttributes = parseConcatAttributes;
|
||||
const validateInputs = (inputs) => {
|
||||
if (!inputs || inputs.length < 1) {
|
||||
throw new Error('too few inputs');
|
||||
}
|
||||
const inputType = inputs[0].type;
|
||||
const inputDimensionality = inputs[0].dims.length;
|
||||
// TODO: Support string concat
|
||||
if (inputType === 'string') {
|
||||
throw new Error('string tensor is not supported yet');
|
||||
}
|
||||
for (const input of inputs) {
|
||||
// make sure types of all inputs match
|
||||
if (input.type !== inputType) {
|
||||
throw new Error('input tensors should be one type');
|
||||
}
|
||||
// make sure the dimensionality of all inputs are the same
|
||||
if (input.dims.length !== inputDimensionality) {
|
||||
throw new Error('input tensors should have the same shape');
|
||||
}
|
||||
}
|
||||
};
|
||||
//# sourceMappingURL=concat.js.map
|
||||
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/concat.js.map
generated
vendored
Normal file
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/concat.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
195
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/concat.ts
generated
vendored
Normal file
195
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/concat.ts
generated
vendored
Normal file
@@ -0,0 +1,195 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../../../attribute-with-cache-key';
|
||||
import {Graph} from '../../../graph';
|
||||
import {OperatorImplementation, OperatorInitialization} from '../../../operators';
|
||||
import {Tensor} from '../../../tensor';
|
||||
import {WebGLInferenceHandler} from '../inference-handler';
|
||||
import {ProgramInfo, ProgramInfoLoader, ProgramMetadata, TextureType} from '../types';
|
||||
|
||||
import {createPackedConcatProgramInfoLoader} from './concat-packed';
|
||||
|
||||
export interface ConcatAttributes extends AttributeWithCacheKey {
|
||||
readonly axis: number;
|
||||
}
|
||||
|
||||
export const concat: OperatorImplementation<ConcatAttributes> =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: ConcatAttributes): Tensor[] => {
|
||||
validateInputs(inputs);
|
||||
if (inferenceHandler.session.pack && inputs[0].dims.length > 1) {
|
||||
const output =
|
||||
inferenceHandler.run(createPackedConcatProgramInfoLoader(inferenceHandler, inputs, attributes), inputs);
|
||||
return [output];
|
||||
} else {
|
||||
const output =
|
||||
inferenceHandler.run(createUnpackedConcatProgramInfoLoader(inferenceHandler, inputs, attributes), inputs);
|
||||
return [output];
|
||||
}
|
||||
};
|
||||
|
||||
const createUnpackedConcatProgramMetadata = (inputCount: number, cacheHint: string) => ({
|
||||
name: 'Concat',
|
||||
inputNames: Array.from({length: inputCount}, (v, i) => `X${i}`),
|
||||
inputTypes: Array(inputCount).fill(TextureType.unpacked),
|
||||
cacheHint
|
||||
});
|
||||
|
||||
const createUnpackedConcatProgramInfo =
|
||||
(handler: WebGLInferenceHandler, metadata: ProgramMetadata, inputs: Tensor[], axis: number): ProgramInfo => {
|
||||
const inputShape = inputs[0].dims.slice();
|
||||
if (axis >= inputShape.length || axis < (-1 * inputShape.length)) {
|
||||
throw new Error('axis specified for concat doesn\'t match input dimensionality');
|
||||
}
|
||||
if (axis < 0) {
|
||||
axis = inputShape.length + axis;
|
||||
}
|
||||
// ensure all of the non-concatenated axes match each other
|
||||
// calculate the shape of the output tensor while we do that
|
||||
const outputShape = inputShape.slice(0);
|
||||
for (let i = 1; i < inputs.length; i++) {
|
||||
const dataNShape = inputs[i].dims.slice();
|
||||
for (let axisIndex = 0; axisIndex < inputShape.length; axisIndex++) {
|
||||
// add to the placeholder for computing output shape
|
||||
if (axisIndex === axis) {
|
||||
outputShape[axis] += dataNShape[axisIndex];
|
||||
}
|
||||
// ensure all non-cancatenated axes match each other
|
||||
else if (inputShape[axisIndex] !== dataNShape[axisIndex]) {
|
||||
throw new Error('non concat dimensions must match');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const rank = outputShape.length;
|
||||
|
||||
const sizeInConcatAxis = new Array<number>(inputs.length);
|
||||
let previousSum = 0;
|
||||
for (let i = 0; i < sizeInConcatAxis.length; ++i) {
|
||||
previousSum += inputs[i].dims[axis];
|
||||
sizeInConcatAxis[i] = previousSum;
|
||||
}
|
||||
|
||||
let getTextureIndexWhereDataResidesMethod = '';
|
||||
// in most cases linear search is sufficient, as in most scenarios, only 2 tensors are concatenated
|
||||
if (inputs.length < 5) {
|
||||
getTextureIndexWhereDataResidesMethod = getTextureIndexWhereDataResidesLinearSearch(sizeInConcatAxis);
|
||||
} else {
|
||||
getTextureIndexWhereDataResidesMethod = getTextureIndexWhereDataResidesBinarySearch(sizeInConcatAxis);
|
||||
}
|
||||
|
||||
const fetchDataFromCorrectTextureMethod = getFetchDataFromCorrectTextureMethod(inputs.length, rank);
|
||||
const getSizeInConcatAxisValueFromIndexMethod = getGetSizeInConcatAxisValueFromIndexMethod(sizeInConcatAxis);
|
||||
const shaderSource = `
|
||||
${fetchDataFromCorrectTextureMethod}
|
||||
${getSizeInConcatAxisValueFromIndexMethod}
|
||||
${getTextureIndexWhereDataResidesMethod}
|
||||
float process(int indices[${rank}]) {
|
||||
int textureIndex = getTextureWhereDataResides (indices[${axis}]);
|
||||
|
||||
if(textureIndex != 0) {
|
||||
indices[${axis}] = indices[${axis}] - int(getSizeInConcatAxisValueFromIndex(textureIndex-int(1)));
|
||||
}
|
||||
|
||||
return fetchDataFromCorrectTexture(textureIndex, indices);
|
||||
}`;
|
||||
return {
|
||||
...metadata,
|
||||
output: {dims: outputShape, type: inputs[0].type, textureType: TextureType.unpacked},
|
||||
shaderSource,
|
||||
};
|
||||
};
|
||||
|
||||
const createUnpackedConcatProgramInfoLoader =
|
||||
(handler: WebGLInferenceHandler, inputs: Tensor[], attributes: ConcatAttributes): ProgramInfoLoader => {
|
||||
const metadata = createUnpackedConcatProgramMetadata(inputs.length, attributes.cacheKey);
|
||||
return {...metadata, get: () => createUnpackedConcatProgramInfo(handler, metadata, inputs, attributes.axis)};
|
||||
};
|
||||
|
||||
const getTextureIndexWhereDataResidesLinearSearch = (sizeInConcatAxis: number[]): string => {
|
||||
const searchAxis = sizeInConcatAxis.map((size, i) => `if(index<${size}) {return ${i};}
|
||||
`);
|
||||
return `int getTextureWhereDataResides(int index) {
|
||||
${searchAxis.join('')}
|
||||
}`;
|
||||
};
|
||||
|
||||
// TODO: Implement BinarySearch in GLSL
|
||||
const getTextureIndexWhereDataResidesBinarySearch = (sizeInConcatAxis: number[]): string =>
|
||||
getTextureIndexWhereDataResidesLinearSearch(sizeInConcatAxis);
|
||||
|
||||
const getFetchDataFromCorrectTextureMethod = (numberOfTensors: number, tensorRank: number) => {
|
||||
const codeLines: string[] = [`float fetchDataFromCorrectTexture(int textureIndex, int indices[${tensorRank}]) {`];
|
||||
for (let i = 0; i < numberOfTensors; ++i) {
|
||||
if (i === 0) {
|
||||
codeLines.push(
|
||||
'\t' +
|
||||
`if (textureIndex == ${i}) { return _X${i}(indices); }`);
|
||||
} else if (i === numberOfTensors - 1) {
|
||||
codeLines.push(
|
||||
'\t' +
|
||||
`else { return _X${i}(indices); }`);
|
||||
} else {
|
||||
codeLines.push(
|
||||
'\t' +
|
||||
`else if (textureIndex == ${i}) { return _X${i}(indices); }`);
|
||||
}
|
||||
}
|
||||
codeLines.push(
|
||||
'\t' +
|
||||
'}');
|
||||
return codeLines.join('\n');
|
||||
};
|
||||
|
||||
const getGetSizeInConcatAxisValueFromIndexMethod = (sizeInConcatAxis: number[]): string => {
|
||||
const codeLines: string[] = ['int getSizeInConcatAxisValueFromIndex(int index) {'];
|
||||
for (let i = 0; i < sizeInConcatAxis.length; ++i) {
|
||||
if (i === 0) {
|
||||
codeLines.push(
|
||||
'\t' +
|
||||
`if (index == ${i}) { return ${sizeInConcatAxis[i]}; }`);
|
||||
} else if (i === sizeInConcatAxis.length - 1) {
|
||||
codeLines.push(
|
||||
'\t' +
|
||||
`else { return ${sizeInConcatAxis[i]}; }`);
|
||||
} else {
|
||||
codeLines.push(
|
||||
'\t' +
|
||||
`else if (index == ${i}) { return ${sizeInConcatAxis[i]}; }`);
|
||||
}
|
||||
}
|
||||
codeLines.push(
|
||||
'\t' +
|
||||
'}');
|
||||
|
||||
return codeLines.join('\n');
|
||||
};
|
||||
|
||||
export const parseConcatAttributes: OperatorInitialization<ConcatAttributes> = (node: Graph.Node): ConcatAttributes =>
|
||||
createAttributeWithCacheKey({axis: node.attributes.getInt('axis')});
|
||||
|
||||
const validateInputs = (inputs: Tensor[]): void => {
|
||||
if (!inputs || inputs.length < 1) {
|
||||
throw new Error('too few inputs');
|
||||
}
|
||||
|
||||
const inputType = inputs[0].type;
|
||||
const inputDimensionality = inputs[0].dims.length;
|
||||
|
||||
// TODO: Support string concat
|
||||
if (inputType === 'string') {
|
||||
throw new Error('string tensor is not supported yet');
|
||||
}
|
||||
|
||||
for (const input of inputs) {
|
||||
// make sure types of all inputs match
|
||||
if (input.type !== inputType) {
|
||||
throw new Error('input tensors should be one type');
|
||||
}
|
||||
|
||||
// make sure the dimensionality of all inputs are the same
|
||||
if (input.dims.length !== inputDimensionality) {
|
||||
throw new Error('input tensors should have the same shape');
|
||||
}
|
||||
}
|
||||
};
|
||||
73
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/conv-grouped.js
generated
vendored
Normal file
73
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/conv-grouped.js
generated
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createUnpackedGroupedConvProgramInfoLoader = void 0;
|
||||
const instrument_1 = require("../../../instrument");
|
||||
const glsl_source_1 = require("../glsl-source");
|
||||
const types_1 = require("../types");
|
||||
const conv_1 = require("./conv");
|
||||
const fuse_utils_1 = require("./fuse-utils");
|
||||
const createUnpackedGroupedConvProgramMetadata = (hasBias, cacheHint) => ({
|
||||
name: 'GroupedConv',
|
||||
inputNames: hasBias ? ['X', 'W', 'Bias'] : ['X', 'W'],
|
||||
inputTypes: hasBias ? [types_1.TextureType.unpacked, types_1.TextureType.unpacked, types_1.TextureType.unpacked] :
|
||||
[types_1.TextureType.unpacked, types_1.TextureType.unpacked],
|
||||
cacheHint
|
||||
});
|
||||
const createUnpackedGroupedConvProgramInfo = (inferenceHandler, inputs, metadata, attributes) => {
|
||||
const hasBias = inputs.length > 2;
|
||||
const processBias = hasBias ? 'value += getBias(output_channel);' : '';
|
||||
const xShape = inputs[0].dims.slice();
|
||||
const wShape = inputs[1].dims.slice();
|
||||
const outputChannelsPerGroup = wShape[0] / attributes.group;
|
||||
instrument_1.Logger.verbose('GroupedConv', `autpPad:${attributes.autoPad}, dilations:${attributes.dilations}, group:${attributes.group}, kernelShape:${attributes.kernelShape}, pads:${attributes.pads}, strides:${attributes.strides}`);
|
||||
const outputShape = (0, conv_1.calculateOutputShape)(xShape, wShape, attributes.dilations, attributes.pads, attributes.strides);
|
||||
const glsl = (0, glsl_source_1.getGlsl)(inferenceHandler.session.backend.glContext.version);
|
||||
const { activationFunction, applyActivation } = (0, fuse_utils_1.getActivationSnippet)(attributes);
|
||||
const shaderSource = `
|
||||
const ivec2 strides = ivec2(${attributes.strides[0]}, ${attributes.strides[1]});
|
||||
const ivec2 pads = ivec2(${attributes.pads[0]}, ${attributes.pads[1]});
|
||||
${activationFunction}
|
||||
void main() {
|
||||
ivec4 coords = getOutputCoords();
|
||||
int batch = coords.x;
|
||||
int output_channel = coords.y;
|
||||
ivec2 xRCCorner = coords.zw * strides - pads;
|
||||
int group_id = output_channel / ${outputChannelsPerGroup};
|
||||
|
||||
float value = 0.0;
|
||||
for (int wInChannel = 0; wInChannel < ${wShape[1]}; wInChannel++) {
|
||||
int input_channel = group_id * ${wShape[1]} + wInChannel;
|
||||
for (int wHeight = 0; wHeight < ${wShape[2]}; wHeight++) {
|
||||
int xHeight = xRCCorner.x + wHeight * ${attributes.dilations[0]};
|
||||
|
||||
if (xHeight < 0 || xHeight >= ${xShape[2]}) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int wWidth = 0; wWidth < ${wShape[3]}; wWidth++) {
|
||||
int xWidth = xRCCorner.y + wWidth * ${attributes.dilations[1]};
|
||||
if (xWidth < 0 || xWidth >= ${xShape[3]}) {
|
||||
continue;
|
||||
}
|
||||
|
||||
float xVal = getX(batch, input_channel, xWidth, xHeight);
|
||||
float wVal = getW(output_channel, wInChannel, wWidth, wHeight);
|
||||
value += xVal*wVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
${processBias}
|
||||
${applyActivation}
|
||||
${glsl.output} = vec4(value, .0, .0, .0);
|
||||
}
|
||||
`;
|
||||
return Object.assign(Object.assign({}, metadata), { output: { dims: outputShape, type: inputs[0].type, textureType: types_1.TextureType.unpacked }, shaderSource, hasMain: true });
|
||||
};
|
||||
const createUnpackedGroupedConvProgramInfoLoader = (inferenceHandler, inputs, attributes) => {
|
||||
const metadata = createUnpackedGroupedConvProgramMetadata(inputs.length > 2, attributes.cacheKey);
|
||||
return Object.assign(Object.assign({}, metadata), { get: () => createUnpackedGroupedConvProgramInfo(inferenceHandler, inputs, metadata, attributes) });
|
||||
};
|
||||
exports.createUnpackedGroupedConvProgramInfoLoader = createUnpackedGroupedConvProgramInfoLoader;
|
||||
//# sourceMappingURL=conv-grouped.js.map
|
||||
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/conv-grouped.js.map
generated
vendored
Normal file
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/conv-grouped.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"conv-grouped.js","sourceRoot":"","sources":["conv-grouped.ts"],"names":[],"mappings":"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"}
|
||||
92
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/conv-grouped.ts
generated
vendored
Normal file
92
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/conv-grouped.ts
generated
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import {Logger} from '../../../instrument';
|
||||
import {Tensor} from '../../../tensor';
|
||||
import {getGlsl} from '../glsl-source';
|
||||
import {WebGLInferenceHandler} from '../inference-handler';
|
||||
import {ProgramInfo, ProgramInfoLoader, ProgramMetadata, TextureType} from '../types';
|
||||
|
||||
import {calculateOutputShape, ConvAttributes} from './conv';
|
||||
import {getActivationSnippet} from './fuse-utils';
|
||||
|
||||
const createUnpackedGroupedConvProgramMetadata = (hasBias: boolean, cacheHint: string): ProgramMetadata => ({
|
||||
name: 'GroupedConv',
|
||||
inputNames: hasBias ? ['X', 'W', 'Bias'] : ['X', 'W'],
|
||||
inputTypes: hasBias ? [TextureType.unpacked, TextureType.unpacked, TextureType.unpacked] :
|
||||
[TextureType.unpacked, TextureType.unpacked],
|
||||
cacheHint
|
||||
});
|
||||
|
||||
const createUnpackedGroupedConvProgramInfo =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: readonly Tensor[], metadata: ProgramMetadata,
|
||||
attributes: ConvAttributes): ProgramInfo => {
|
||||
const hasBias = inputs.length > 2;
|
||||
const processBias = hasBias ? 'value += getBias(output_channel);' : '';
|
||||
const xShape = inputs[0].dims.slice();
|
||||
const wShape = inputs[1].dims.slice();
|
||||
const outputChannelsPerGroup = wShape[0] / attributes.group;
|
||||
Logger.verbose(
|
||||
'GroupedConv',
|
||||
`autpPad:${attributes.autoPad}, dilations:${attributes.dilations}, group:${attributes.group}, kernelShape:${
|
||||
attributes.kernelShape}, pads:${attributes.pads}, strides:${attributes.strides}`);
|
||||
const outputShape =
|
||||
calculateOutputShape(xShape, wShape, attributes.dilations, attributes.pads, attributes.strides);
|
||||
const glsl = getGlsl(inferenceHandler.session.backend.glContext.version);
|
||||
const {activationFunction, applyActivation} = getActivationSnippet(attributes);
|
||||
|
||||
const shaderSource = `
|
||||
const ivec2 strides = ivec2(${attributes.strides[0]}, ${attributes.strides[1]});
|
||||
const ivec2 pads = ivec2(${attributes.pads[0]}, ${attributes.pads[1]});
|
||||
${activationFunction}
|
||||
void main() {
|
||||
ivec4 coords = getOutputCoords();
|
||||
int batch = coords.x;
|
||||
int output_channel = coords.y;
|
||||
ivec2 xRCCorner = coords.zw * strides - pads;
|
||||
int group_id = output_channel / ${outputChannelsPerGroup};
|
||||
|
||||
float value = 0.0;
|
||||
for (int wInChannel = 0; wInChannel < ${wShape[1]}; wInChannel++) {
|
||||
int input_channel = group_id * ${wShape[1]} + wInChannel;
|
||||
for (int wHeight = 0; wHeight < ${wShape[2]}; wHeight++) {
|
||||
int xHeight = xRCCorner.x + wHeight * ${attributes.dilations[0]};
|
||||
|
||||
if (xHeight < 0 || xHeight >= ${xShape[2]}) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int wWidth = 0; wWidth < ${wShape[3]}; wWidth++) {
|
||||
int xWidth = xRCCorner.y + wWidth * ${attributes.dilations[1]};
|
||||
if (xWidth < 0 || xWidth >= ${xShape[3]}) {
|
||||
continue;
|
||||
}
|
||||
|
||||
float xVal = getX(batch, input_channel, xWidth, xHeight);
|
||||
float wVal = getW(output_channel, wInChannel, wWidth, wHeight);
|
||||
value += xVal*wVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
${processBias}
|
||||
${applyActivation}
|
||||
${glsl.output} = vec4(value, .0, .0, .0);
|
||||
}
|
||||
`;
|
||||
return {
|
||||
...metadata,
|
||||
output: {dims: outputShape, type: inputs[0].type, textureType: TextureType.unpacked},
|
||||
shaderSource,
|
||||
hasMain: true,
|
||||
};
|
||||
};
|
||||
|
||||
export const createUnpackedGroupedConvProgramInfoLoader =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: readonly Tensor[], attributes: ConvAttributes):
|
||||
ProgramInfoLoader => {
|
||||
const metadata = createUnpackedGroupedConvProgramMetadata(inputs.length > 2, attributes.cacheKey);
|
||||
return {
|
||||
...metadata,
|
||||
get: () => createUnpackedGroupedConvProgramInfo(inferenceHandler, inputs, metadata, attributes)
|
||||
};
|
||||
};
|
||||
36
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/conv-pack.js
generated
vendored
Normal file
36
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/conv-pack.js
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.conv2DPacked = exports.conv2DPackedPointwise = void 0;
|
||||
const conv_1 = require("./conv");
|
||||
const im2col_pack_1 = require("./im2col-pack");
|
||||
const matmul_pack_1 = require("./matmul-pack");
|
||||
const conv2DPackedPointwise = (inferenceHandler, inputs, attributes) => {
|
||||
const xshape = inputs[0].dims;
|
||||
const kshape = inputs[1].dims;
|
||||
const outputShape = (0, conv_1.calculateOutputShape)(xshape, kshape, attributes.dilations, attributes.pads, attributes.strides);
|
||||
const reshapedX = inferenceHandler.reshapePacked(inputs[0], [xshape[1], xshape[2] * xshape[3]]);
|
||||
const reshapedK = inferenceHandler.reshapePacked(inputs[1], [kshape[0], kshape[1]]);
|
||||
const matmulInputs = inputs.length > 2 ? [reshapedK, reshapedX, inputs[2]] : [reshapedK, reshapedX];
|
||||
const matmulOutput = inferenceHandler.run((0, matmul_pack_1.createPackedMatmulProgramInfoLoader)(inferenceHandler, matmulInputs, attributes), matmulInputs);
|
||||
return inferenceHandler.reshapePacked(matmulOutput, outputShape);
|
||||
};
|
||||
exports.conv2DPackedPointwise = conv2DPackedPointwise;
|
||||
const conv2DPacked = (inferenceHandler, inputs, attributes) => {
|
||||
const xshape = inputs[0].dims;
|
||||
const kshape = inputs[1].dims;
|
||||
const outputShape = (0, conv_1.calculateOutputShape)(xshape, kshape, attributes.dilations, attributes.pads, attributes.strides);
|
||||
// run im2col
|
||||
const im2colOutput = inferenceHandler.run((0, im2col_pack_1.createPackedIm2ColProgramInfoLoader)(inferenceHandler, inputs[0], inputs[1], outputShape, attributes), [inputs[0]]);
|
||||
// reshape kernel
|
||||
const kernelReshaped = inferenceHandler.reshapePacked(inputs[1], [kshape[0], kshape[1] * kshape[2] * kshape[3]]);
|
||||
// run matmul
|
||||
const matmulInputs = (inputs.length === 3) ? [kernelReshaped, im2colOutput, inputs[2]] : [kernelReshaped, im2colOutput];
|
||||
const matmulOutput = inferenceHandler.run((0, matmul_pack_1.createPackedMatmulProgramInfoLoader)(inferenceHandler, matmulInputs, attributes), matmulInputs);
|
||||
// reshape output
|
||||
const outputReshaped = inferenceHandler.reshapePacked(matmulOutput, outputShape);
|
||||
return outputReshaped;
|
||||
};
|
||||
exports.conv2DPacked = conv2DPacked;
|
||||
//# sourceMappingURL=conv-pack.js.map
|
||||
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/conv-pack.js.map
generated
vendored
Normal file
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/conv-pack.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"conv-pack.js","sourceRoot":"","sources":["conv-pack.ts"],"names":[],"mappings":";AAAA,4DAA4D;AAC5D,kCAAkC;;;AAKlC,iCAA4D;AAC5D,+CAAkE;AAClE,+CAAkE;AAE3D,MAAM,qBAAqB,GAC9B,CAAC,gBAAuC,EAAE,MAAyB,EAAE,UAA0B,EAAU,EAAE;IACzG,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC9B,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC9B,MAAM,WAAW,GACb,IAAA,2BAAoB,EAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,SAAS,EAAE,UAAU,CAAC,IAAI,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;IACpG,MAAM,SAAS,GAAG,gBAAgB,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAChG,MAAM,SAAS,GAAG,gBAAgB,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAEpF,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IACpG,MAAM,YAAY,GAAG,gBAAgB,CAAC,GAAG,CACrC,IAAA,iDAAmC,EAAC,gBAAgB,EAAE,YAAY,EAAE,UAAU,CAAC,EAAE,YAAY,CAAC,CAAC;IACnG,OAAO,gBAAgB,CAAC,aAAa,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC;AACnE,CAAC,CAAC;AAbO,QAAA,qBAAqB,yBAa5B;AAEC,MAAM,YAAY,GACrB,CAAC,gBAAuC,EAAE,MAAyB,EAAE,UAA0B,EAAU,EAAE;IACzG,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC9B,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC9B,MAAM,WAAW,GACb,IAAA,2BAAoB,EAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,SAAS,EAAE,UAAU,CAAC,IAAI,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;IAEpG,aAAa;IACb,MAAM,YAAY,GAAG,gBAAgB,CAAC,GAAG,CACrC,IAAA,iDAAmC,EAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,UAAU,CAAC,EACpG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAEjB,iBAAiB;IACjB,MAAM,cAAc,GAAG,gBAAgB,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAEjH,aAAa;IACb,MAAM,YAAY,GACd,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,EAAE,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,cAAc,EAAE,YAAY,CAAC,CAAC;IACvG,MAAM,YAAY,GAAG,gBAAgB,CAAC,GAAG,CACrC,IAAA,iDAAmC,EAAC,gBAAgB,EAAE,YAAY,EAAE,UAAU,CAAC,EAAE,YAAY,CAAC,CAAC;IAEnG,iBAAiB;IACjB,MAAM,cAAc,GAAG,gBAAgB,CAAC,aAAa,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC;IACjF,OAAO,cAAc,CAAC;AACxB,CAAC,CAAC;AAxBO,QAAA,YAAY,gBAwBnB"}
|
||||
50
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/conv-pack.ts
generated
vendored
Normal file
50
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/conv-pack.ts
generated
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import {Tensor} from '../../../tensor';
|
||||
import {WebGLInferenceHandler} from '../inference-handler';
|
||||
|
||||
import {calculateOutputShape, ConvAttributes} from './conv';
|
||||
import {createPackedIm2ColProgramInfoLoader} from './im2col-pack';
|
||||
import {createPackedMatmulProgramInfoLoader} from './matmul-pack';
|
||||
|
||||
export const conv2DPackedPointwise =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: readonly Tensor[], attributes: ConvAttributes): Tensor => {
|
||||
const xshape = inputs[0].dims;
|
||||
const kshape = inputs[1].dims;
|
||||
const outputShape =
|
||||
calculateOutputShape(xshape, kshape, attributes.dilations, attributes.pads, attributes.strides);
|
||||
const reshapedX = inferenceHandler.reshapePacked(inputs[0], [xshape[1], xshape[2] * xshape[3]]);
|
||||
const reshapedK = inferenceHandler.reshapePacked(inputs[1], [kshape[0], kshape[1]]);
|
||||
|
||||
const matmulInputs = inputs.length > 2 ? [reshapedK, reshapedX, inputs[2]] : [reshapedK, reshapedX];
|
||||
const matmulOutput = inferenceHandler.run(
|
||||
createPackedMatmulProgramInfoLoader(inferenceHandler, matmulInputs, attributes), matmulInputs);
|
||||
return inferenceHandler.reshapePacked(matmulOutput, outputShape);
|
||||
};
|
||||
|
||||
export const conv2DPacked =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: readonly Tensor[], attributes: ConvAttributes): Tensor => {
|
||||
const xshape = inputs[0].dims;
|
||||
const kshape = inputs[1].dims;
|
||||
const outputShape =
|
||||
calculateOutputShape(xshape, kshape, attributes.dilations, attributes.pads, attributes.strides);
|
||||
|
||||
// run im2col
|
||||
const im2colOutput = inferenceHandler.run(
|
||||
createPackedIm2ColProgramInfoLoader(inferenceHandler, inputs[0], inputs[1], outputShape, attributes),
|
||||
[inputs[0]]);
|
||||
|
||||
// reshape kernel
|
||||
const kernelReshaped = inferenceHandler.reshapePacked(inputs[1], [kshape[0], kshape[1] * kshape[2] * kshape[3]]);
|
||||
|
||||
// run matmul
|
||||
const matmulInputs =
|
||||
(inputs.length === 3) ? [kernelReshaped, im2colOutput, inputs[2]] : [kernelReshaped, im2colOutput];
|
||||
const matmulOutput = inferenceHandler.run(
|
||||
createPackedMatmulProgramInfoLoader(inferenceHandler, matmulInputs, attributes), matmulInputs);
|
||||
|
||||
// reshape output
|
||||
const outputReshaped = inferenceHandler.reshapePacked(matmulOutput, outputShape);
|
||||
return outputReshaped;
|
||||
};
|
||||
198
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/conv-transpose.js
generated
vendored
Normal file
198
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/conv-transpose.js
generated
vendored
Normal file
@@ -0,0 +1,198 @@
|
||||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.parseConvTransposeAttributes = exports.convTranspose = void 0;
|
||||
const attribute_with_cache_key_1 = require("../../../attribute-with-cache-key");
|
||||
const glsl_source_1 = require("../glsl-source");
|
||||
const types_1 = require("../types");
|
||||
const fuse_utils_1 = require("./fuse-utils");
|
||||
const computeTotalPad = (inDim, stride, adj, kernel, dilation, outSize) => (inDim - 1) * stride + adj + (kernel - 1) * dilation + 1 - outSize;
|
||||
const distributePadding = (totalPad, autoPad, pads, head, tail) => {
|
||||
const smallPad = Math.floor(totalPad / 2);
|
||||
if (autoPad === 'SAME_UPPER') {
|
||||
pads[head] = smallPad;
|
||||
pads[tail] = totalPad - smallPad;
|
||||
}
|
||||
else if (autoPad === 'SAME_LOWER') {
|
||||
pads[head] = totalPad - smallPad;
|
||||
pads[tail] = smallPad;
|
||||
}
|
||||
};
|
||||
const calculateOutputShapeAndPads = (inputShape, kernelShape, dilations, autoPad, pads, strides, outputPadding, outputShape) => {
|
||||
const spatialRank = inputShape.length - 2;
|
||||
const updateShape = outputShape.length === 0;
|
||||
for (let i = 0; i < spatialRank; ++i) {
|
||||
const outSize = updateShape ? inputShape[i + 2] * strides[i] : outputShape[i];
|
||||
const totalPad = computeTotalPad(inputShape[i + 2], strides[i], pads[i], kernelShape[i], dilations[i], outSize);
|
||||
distributePadding(totalPad, autoPad, pads, i, i + spatialRank);
|
||||
if (updateShape) {
|
||||
outputShape.push(strides[i] * (inputShape[i + 2] - 1) + outputPadding[i] + (kernelShape[i] - 1) * dilations[i] + 1 -
|
||||
pads[i] - pads[i + spatialRank]);
|
||||
}
|
||||
}
|
||||
};
|
||||
const convTranspose = (inferenceHandler, inputs, attributes) => {
|
||||
validateInputs(inputs, attributes); // currently will fail if not convTranspose2D
|
||||
return convTranspose2d(inferenceHandler, inputs, attributes);
|
||||
};
|
||||
exports.convTranspose = convTranspose;
|
||||
const convTranspose2d = (inferenceHandler, inputs, attributes) => {
|
||||
const adjustedAttributes = getAdjustedConvTransposeAttributes(attributes, inputs);
|
||||
return [convTranspose2DUnpacked(inferenceHandler, inputs, adjustedAttributes)];
|
||||
};
|
||||
const createConvTransposeProgramMetadata = (hasBias, cacheHint) => ({
|
||||
name: 'ConvTranspose',
|
||||
inputNames: hasBias ? ['X', 'W', 'B'] : ['X', 'W'],
|
||||
inputTypes: hasBias ? [types_1.TextureType.unpacked, types_1.TextureType.unpacked, types_1.TextureType.unpacked] :
|
||||
[types_1.TextureType.unpacked, types_1.TextureType.unpacked],
|
||||
cacheHint
|
||||
});
|
||||
const createUnpackedConvTransposeProgramInfo = (inferenceHandler, inputs, metadata, attributes) => {
|
||||
const hasBias = inputs.length > 2;
|
||||
const valueInit = hasBias ? 'getB(output_channel)' : '0.0';
|
||||
const xShape = inputs[0].dims;
|
||||
const wShape = inputs[1].dims;
|
||||
const outputChannelsPerGroup = wShape[1];
|
||||
const inputChannelsPerGroup = wShape[0] / attributes.group;
|
||||
const outputShape = [inputs[0].dims[0], inputs[1].dims[1] * attributes.group, ...attributes.outputShape];
|
||||
const glsl = (0, glsl_source_1.getGlsl)(inferenceHandler.session.backend.glContext.version);
|
||||
const { activationFunction, applyActivation } = (0, fuse_utils_1.getActivationSnippet)(attributes);
|
||||
const shaderSource = `
|
||||
const ivec2 strides = ivec2(${attributes.strides[0]}, ${attributes.strides[1]});
|
||||
const ivec2 pads = ivec2(${attributes.pads[0]}, ${attributes.pads[1]});
|
||||
${activationFunction}
|
||||
void main() {
|
||||
ivec4 coords = getOutputCoords();
|
||||
int batch = coords.x;
|
||||
int output_channel = coords.y;
|
||||
|
||||
ivec2 loc = coords.zw + pads;
|
||||
|
||||
int group_id = output_channel / ${outputChannelsPerGroup};
|
||||
int wOutChannel = output_channel - group_id * ${outputChannelsPerGroup};
|
||||
|
||||
float value = ${valueInit};
|
||||
for (int inChannelOffset = 0; inChannelOffset < ${inputChannelsPerGroup}; inChannelOffset++) {
|
||||
int input_channel = group_id * ${inputChannelsPerGroup} + inChannelOffset;
|
||||
for (int wWOff = 0; wWOff < ${wShape[2]}; wWOff++) {
|
||||
for (int wHOff = 0; wHOff < ${wShape[3]}; wHOff++) {
|
||||
ivec2 wOff = ivec2(wWOff * ${attributes.dilations[0]}, wHOff * ${attributes.dilations[1]});
|
||||
ivec2 wLoc = loc - wOff;
|
||||
ivec2 wLocIn = wLoc / strides;
|
||||
if (
|
||||
wLocIn * strides == wLoc &&
|
||||
wLocIn.x >= 0 && wLocIn.x < ${xShape[2]} &&
|
||||
wLocIn.y >= 0 && wLocIn.y < ${xShape[3]}
|
||||
) {
|
||||
float xVal = getX(batch, input_channel, wLocIn.y, wLocIn.x);
|
||||
float wVal = getW(input_channel, wOutChannel, wHOff, wWOff);
|
||||
value += xVal * wVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
${applyActivation}
|
||||
${glsl.output} = vec4(value, .0, .0, .0);
|
||||
}
|
||||
`;
|
||||
return Object.assign(Object.assign({}, metadata), { output: { dims: outputShape, type: inputs[0].type, textureType: types_1.TextureType.unpacked }, shaderSource, hasMain: true });
|
||||
};
|
||||
const createUnpackedConvTransposeProgramInfoLoader = (inferenceHandler, inputs, attributes) => {
|
||||
const metadata = createConvTransposeProgramMetadata(inputs.length > 2, attributes.cacheKey);
|
||||
return Object.assign(Object.assign({}, metadata), { get: () => createUnpackedConvTransposeProgramInfo(inferenceHandler, inputs, metadata, attributes) });
|
||||
};
|
||||
const convTranspose2DUnpacked = (inferenceHandler, inputs, attributes) => {
|
||||
const result = inferenceHandler.run(createUnpackedConvTransposeProgramInfoLoader(inferenceHandler, inputs, attributes), inputs);
|
||||
return result;
|
||||
};
|
||||
const getAdjustedConvTransposeAttributes = (attributes, inputs) => {
|
||||
const kernelShape = attributes.kernelShape.slice();
|
||||
// if kernelShape is not specified in the attributes of this op, infer it from the weight tensor dims
|
||||
if (attributes.kernelShape.length === 0) {
|
||||
for (let i = 2; i < inputs[1].dims.length; ++i) {
|
||||
kernelShape.push(inputs[1].dims[i]);
|
||||
}
|
||||
}
|
||||
const pads = attributes.pads.slice();
|
||||
const outputShape = attributes.outputShape.slice();
|
||||
const inputShape = inputs[0].dims;
|
||||
// If outputShape is not specified in the attributes of this op, infer it from the parameters
|
||||
// Similarly, automatically infer pads if not specified
|
||||
calculateOutputShapeAndPads(inputShape, kernelShape, attributes.dilations, attributes.autoPad, pads, attributes.strides, attributes.outputPadding, outputShape);
|
||||
// always return a new object so does not modify the original attributes
|
||||
const newAttributes = Object.assign({}, attributes);
|
||||
Object.assign(newAttributes, { kernelShape, pads, outputShape, cacheKey: attributes.cacheKey });
|
||||
return newAttributes;
|
||||
};
|
||||
const parseConvTransposeAttributes = (node) => {
|
||||
const attributes = node.attributes;
|
||||
const activationAttributes = (0, fuse_utils_1.parseInternalActivationAttributes)(attributes);
|
||||
// TODO : Make this generic enough to compute default attributes for multi-dimensional conv
|
||||
const autoPad = attributes.getString('auto_pad', 'NOTSET');
|
||||
const dilations = attributes.getInts('dilations', [1, 1]);
|
||||
const group = attributes.getInt('group', 1);
|
||||
const kernelShape = attributes.getInts('kernel_shape', []);
|
||||
const outputPadding = attributes.getInts('output_padding', [0, 0]);
|
||||
const outputShape = attributes.getInts('output_shape', []);
|
||||
const pads = attributes.getInts('pads', [0, 0, 0, 0]);
|
||||
const strides = attributes.getInts('strides', [1, 1]);
|
||||
return (0, attribute_with_cache_key_1.createAttributeWithCacheKey)(Object.assign({ autoPad, dilations, group, kernelShape, outputPadding, outputShape, pads, strides }, activationAttributes));
|
||||
};
|
||||
exports.parseConvTransposeAttributes = parseConvTransposeAttributes;
|
||||
const validateInputs = (inputs, attributes) => {
|
||||
// Refer to the below link for all input checks
|
||||
// https://github.com/onnx/onnx/blob/main/docs/Operators.md#Conv
|
||||
if (!inputs || (inputs.length !== 2 && inputs.length !== 3)) {
|
||||
throw new Error('Conv requires 2 or 3 inputs');
|
||||
}
|
||||
// TODO : Need to add support for multi-dimensional conv
|
||||
if (inputs[0].dims.length !== 4 || inputs[1].dims.length !== 4) {
|
||||
throw new Error('currently only support 2-dimensional conv');
|
||||
}
|
||||
// FILTER_IN_CHANNEL should be equal to DATA_CHANNEL
|
||||
const dataChannel = inputs[0].dims[1];
|
||||
const filterInChannel = inputs[1].dims[0];
|
||||
if (dataChannel !== filterInChannel) {
|
||||
throw new Error('FILTER_IN_CHANNEL should be equal to DATA_CHANNEL');
|
||||
}
|
||||
const featureMaps = inputs[1].dims[1] * attributes.group;
|
||||
// if bias is provided it should be 1D and the number of elements should be equal to the number of feature maps
|
||||
if (inputs.length === 3 && (inputs[2].dims.length !== 1 || inputs[2].dims[0] !== featureMaps)) {
|
||||
throw new Error('invalid bias');
|
||||
}
|
||||
const spatialRank = inputs[0].dims.length - 2;
|
||||
// wrong dilations dimension
|
||||
if (attributes.dilations.length !== spatialRank) {
|
||||
throw new Error(`dilations should be ${spatialRank}D`);
|
||||
}
|
||||
// Wrong strides dimension
|
||||
if (attributes.strides.length !== spatialRank) {
|
||||
throw new Error(`strides should be ${spatialRank}D`);
|
||||
}
|
||||
// Wrong pads dimension
|
||||
if (attributes.pads.length !== spatialRank * 2) {
|
||||
throw new Error(`pads should be ${spatialRank * 2}D`);
|
||||
}
|
||||
// Wrong output padding dimension
|
||||
if (attributes.outputPadding.length !== spatialRank) {
|
||||
throw new Error(`output_padding should be ${spatialRank}D`);
|
||||
}
|
||||
// if kernelShape is specified, it's data length must be 2 less than dims length of the weights tensor
|
||||
// (the first 2 dims are batch_size and channels)
|
||||
if (attributes.kernelShape.length !== 0 && attributes.kernelShape.length !== inputs[1].dims.length - 2) {
|
||||
throw new Error('invalid kernel shape');
|
||||
}
|
||||
// as with kernelShape, must have same number of spatial dims as input
|
||||
if (attributes.outputShape.length !== 0 && attributes.outputShape.length !== inputs[0].dims.length - 2) {
|
||||
throw new Error('invalid output shape');
|
||||
}
|
||||
// TODO : Need to add support for float64
|
||||
if (inputs[0].type !== 'float32' || inputs[1].type !== 'float32') {
|
||||
throw new Error('ConvTranspose input(X,W) should be float tensor');
|
||||
}
|
||||
if (inputs.length === 3 && inputs[2].type !== 'float32') {
|
||||
throw new Error('ConvTranspose input(bias) should be float tensor');
|
||||
}
|
||||
};
|
||||
//# sourceMappingURL=conv-transpose.js.map
|
||||
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/conv-transpose.js.map
generated
vendored
Normal file
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/conv-transpose.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
259
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/conv-transpose.ts
generated
vendored
Normal file
259
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/conv-transpose.ts
generated
vendored
Normal file
@@ -0,0 +1,259 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import {createAttributeWithCacheKey} from '../../../attribute-with-cache-key';
|
||||
import {InferenceHandler} from '../../../backend';
|
||||
import {Graph} from '../../../graph';
|
||||
import {OperatorImplementation, OperatorInitialization} from '../../../operators';
|
||||
import {Tensor} from '../../../tensor';
|
||||
import {getGlsl} from '../glsl-source';
|
||||
import {WebGLInferenceHandler} from '../inference-handler';
|
||||
import {ProgramInfo, ProgramInfoLoader, ProgramMetadata, TextureType} from '../types';
|
||||
|
||||
import {ConvAttributes} from './conv';
|
||||
import {getActivationSnippet, parseInternalActivationAttributes} from './fuse-utils';
|
||||
|
||||
const computeTotalPad =
|
||||
(inDim: number, stride: number, adj: number, kernel: number, dilation: number, outSize: number) =>
|
||||
(inDim - 1) * stride + adj + (kernel - 1) * dilation + 1 - outSize;
|
||||
|
||||
const distributePadding = (totalPad: number, autoPad: string, pads: number[], head: number, tail: number) => {
|
||||
const smallPad = Math.floor(totalPad / 2);
|
||||
if (autoPad === 'SAME_UPPER') {
|
||||
pads[head] = smallPad;
|
||||
pads[tail] = totalPad - smallPad;
|
||||
} else if (autoPad === 'SAME_LOWER') {
|
||||
pads[head] = totalPad - smallPad;
|
||||
pads[tail] = smallPad;
|
||||
}
|
||||
};
|
||||
|
||||
const calculateOutputShapeAndPads =
|
||||
(inputShape: readonly number[], kernelShape: readonly number[], dilations: readonly number[], autoPad: string,
|
||||
pads: number[], strides: readonly number[], outputPadding: readonly number[], outputShape: number[]) => {
|
||||
const spatialRank = inputShape.length - 2;
|
||||
const updateShape = outputShape.length === 0;
|
||||
for (let i = 0; i < spatialRank; ++i) {
|
||||
const outSize = updateShape ? inputShape[i + 2] * strides[i] : outputShape[i];
|
||||
const totalPad = computeTotalPad(inputShape[i + 2], strides[i], pads[i], kernelShape[i], dilations[i], outSize);
|
||||
distributePadding(totalPad, autoPad, pads, i, i + spatialRank);
|
||||
if (updateShape) {
|
||||
outputShape.push(
|
||||
strides[i] * (inputShape[i + 2] - 1) + outputPadding[i] + (kernelShape[i] - 1) * dilations[i] + 1 -
|
||||
pads[i] - pads[i + spatialRank]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export interface ConvTransposeAttributes extends ConvAttributes {
|
||||
readonly outputPadding: readonly number[];
|
||||
readonly outputShape: readonly number[];
|
||||
}
|
||||
|
||||
export const convTranspose: OperatorImplementation<ConvTransposeAttributes> =
|
||||
(inferenceHandler: InferenceHandler, inputs: Tensor[], attributes: ConvTransposeAttributes): Tensor[] => {
|
||||
validateInputs(inputs, attributes); // currently will fail if not convTranspose2D
|
||||
return convTranspose2d(inferenceHandler, inputs, attributes);
|
||||
};
|
||||
|
||||
const convTranspose2d: OperatorImplementation<ConvTransposeAttributes> =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: ConvTransposeAttributes): Tensor[] => {
|
||||
const adjustedAttributes = getAdjustedConvTransposeAttributes(attributes, inputs);
|
||||
return [convTranspose2DUnpacked(inferenceHandler, inputs, adjustedAttributes)];
|
||||
};
|
||||
|
||||
const createConvTransposeProgramMetadata = (hasBias: boolean, cacheHint: string) => ({
|
||||
name: 'ConvTranspose',
|
||||
inputNames: hasBias ? ['X', 'W', 'B'] : ['X', 'W'],
|
||||
inputTypes: hasBias ? [TextureType.unpacked, TextureType.unpacked, TextureType.unpacked] :
|
||||
[TextureType.unpacked, TextureType.unpacked],
|
||||
cacheHint
|
||||
});
|
||||
|
||||
const createUnpackedConvTransposeProgramInfo =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: readonly Tensor[], metadata: ProgramMetadata,
|
||||
attributes: ConvTransposeAttributes): ProgramInfo => {
|
||||
const hasBias = inputs.length > 2;
|
||||
const valueInit = hasBias ? 'getB(output_channel)' : '0.0';
|
||||
const xShape = inputs[0].dims;
|
||||
const wShape = inputs[1].dims;
|
||||
const outputChannelsPerGroup = wShape[1];
|
||||
const inputChannelsPerGroup = wShape[0] / attributes.group;
|
||||
const outputShape = [inputs[0].dims[0], inputs[1].dims[1] * attributes.group, ...attributes.outputShape];
|
||||
const glsl = getGlsl(inferenceHandler.session.backend.glContext.version);
|
||||
const {activationFunction, applyActivation} = getActivationSnippet(attributes);
|
||||
|
||||
const shaderSource = `
|
||||
const ivec2 strides = ivec2(${attributes.strides[0]}, ${attributes.strides[1]});
|
||||
const ivec2 pads = ivec2(${attributes.pads[0]}, ${attributes.pads[1]});
|
||||
${activationFunction}
|
||||
void main() {
|
||||
ivec4 coords = getOutputCoords();
|
||||
int batch = coords.x;
|
||||
int output_channel = coords.y;
|
||||
|
||||
ivec2 loc = coords.zw + pads;
|
||||
|
||||
int group_id = output_channel / ${outputChannelsPerGroup};
|
||||
int wOutChannel = output_channel - group_id * ${outputChannelsPerGroup};
|
||||
|
||||
float value = ${valueInit};
|
||||
for (int inChannelOffset = 0; inChannelOffset < ${inputChannelsPerGroup}; inChannelOffset++) {
|
||||
int input_channel = group_id * ${inputChannelsPerGroup} + inChannelOffset;
|
||||
for (int wWOff = 0; wWOff < ${wShape[2]}; wWOff++) {
|
||||
for (int wHOff = 0; wHOff < ${wShape[3]}; wHOff++) {
|
||||
ivec2 wOff = ivec2(wWOff * ${attributes.dilations[0]}, wHOff * ${attributes.dilations[1]});
|
||||
ivec2 wLoc = loc - wOff;
|
||||
ivec2 wLocIn = wLoc / strides;
|
||||
if (
|
||||
wLocIn * strides == wLoc &&
|
||||
wLocIn.x >= 0 && wLocIn.x < ${xShape[2]} &&
|
||||
wLocIn.y >= 0 && wLocIn.y < ${xShape[3]}
|
||||
) {
|
||||
float xVal = getX(batch, input_channel, wLocIn.y, wLocIn.x);
|
||||
float wVal = getW(input_channel, wOutChannel, wHOff, wWOff);
|
||||
value += xVal * wVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
${applyActivation}
|
||||
${glsl.output} = vec4(value, .0, .0, .0);
|
||||
}
|
||||
`;
|
||||
return {
|
||||
...metadata,
|
||||
output: {dims: outputShape, type: inputs[0].type, textureType: TextureType.unpacked},
|
||||
shaderSource,
|
||||
hasMain: true,
|
||||
};
|
||||
};
|
||||
|
||||
const createUnpackedConvTransposeProgramInfoLoader =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: readonly Tensor[], attributes: ConvTransposeAttributes):
|
||||
ProgramInfoLoader => {
|
||||
const metadata = createConvTransposeProgramMetadata(inputs.length > 2, attributes.cacheKey);
|
||||
return {
|
||||
...metadata,
|
||||
get: () => createUnpackedConvTransposeProgramInfo(inferenceHandler, inputs, metadata, attributes)
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
const convTranspose2DUnpacked =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: readonly Tensor[], attributes: ConvTransposeAttributes):
|
||||
Tensor => {
|
||||
const result = inferenceHandler.run(
|
||||
createUnpackedConvTransposeProgramInfoLoader(inferenceHandler, inputs, attributes), inputs);
|
||||
return result;
|
||||
};
|
||||
|
||||
const getAdjustedConvTransposeAttributes = <T extends ConvTransposeAttributes>(attributes: T, inputs: Tensor[]): T => {
|
||||
const kernelShape = attributes.kernelShape.slice();
|
||||
// if kernelShape is not specified in the attributes of this op, infer it from the weight tensor dims
|
||||
if (attributes.kernelShape.length === 0) {
|
||||
for (let i = 2; i < inputs[1].dims.length; ++i) {
|
||||
kernelShape.push(inputs[1].dims[i]);
|
||||
}
|
||||
}
|
||||
|
||||
const pads = attributes.pads.slice();
|
||||
const outputShape = attributes.outputShape.slice();
|
||||
const inputShape = inputs[0].dims;
|
||||
// If outputShape is not specified in the attributes of this op, infer it from the parameters
|
||||
// Similarly, automatically infer pads if not specified
|
||||
calculateOutputShapeAndPads(
|
||||
inputShape, kernelShape, attributes.dilations, attributes.autoPad, pads, attributes.strides,
|
||||
attributes.outputPadding, outputShape);
|
||||
|
||||
// always return a new object so does not modify the original attributes
|
||||
const newAttributes: T = Object.assign({}, attributes);
|
||||
Object.assign(newAttributes, {kernelShape, pads, outputShape, cacheKey: attributes.cacheKey});
|
||||
return newAttributes;
|
||||
};
|
||||
|
||||
export const parseConvTransposeAttributes: OperatorInitialization<ConvTransposeAttributes> =
|
||||
(node: Graph.Node): ConvTransposeAttributes => {
|
||||
const attributes = node.attributes;
|
||||
const activationAttributes = parseInternalActivationAttributes(attributes);
|
||||
// TODO : Make this generic enough to compute default attributes for multi-dimensional conv
|
||||
const autoPad = attributes.getString('auto_pad', 'NOTSET');
|
||||
const dilations = attributes.getInts('dilations', [1, 1]);
|
||||
const group = attributes.getInt('group', 1);
|
||||
const kernelShape = attributes.getInts('kernel_shape', []);
|
||||
const outputPadding = attributes.getInts('output_padding', [0, 0]);
|
||||
const outputShape = attributes.getInts('output_shape', []);
|
||||
const pads = attributes.getInts('pads', [0, 0, 0, 0]);
|
||||
const strides = attributes.getInts('strides', [1, 1]);
|
||||
|
||||
return createAttributeWithCacheKey(
|
||||
{autoPad, dilations, group, kernelShape, outputPadding, outputShape, pads, strides, ...activationAttributes});
|
||||
};
|
||||
|
||||
const validateInputs = (inputs: Tensor[], attributes: ConvTransposeAttributes): void => {
|
||||
// Refer to the below link for all input checks
|
||||
// https://github.com/onnx/onnx/blob/main/docs/Operators.md#Conv
|
||||
if (!inputs || (inputs.length !== 2 && inputs.length !== 3)) {
|
||||
throw new Error('Conv requires 2 or 3 inputs');
|
||||
}
|
||||
|
||||
// TODO : Need to add support for multi-dimensional conv
|
||||
if (inputs[0].dims.length !== 4 || inputs[1].dims.length !== 4) {
|
||||
throw new Error('currently only support 2-dimensional conv');
|
||||
}
|
||||
|
||||
// FILTER_IN_CHANNEL should be equal to DATA_CHANNEL
|
||||
const dataChannel = inputs[0].dims[1];
|
||||
const filterInChannel = inputs[1].dims[0];
|
||||
if (dataChannel !== filterInChannel) {
|
||||
throw new Error('FILTER_IN_CHANNEL should be equal to DATA_CHANNEL');
|
||||
}
|
||||
|
||||
const featureMaps = inputs[1].dims[1] * attributes.group;
|
||||
|
||||
// if bias is provided it should be 1D and the number of elements should be equal to the number of feature maps
|
||||
if (inputs.length === 3 && (inputs[2].dims.length !== 1 || inputs[2].dims[0] !== featureMaps)) {
|
||||
throw new Error('invalid bias');
|
||||
}
|
||||
|
||||
const spatialRank = inputs[0].dims.length - 2;
|
||||
// wrong dilations dimension
|
||||
if (attributes.dilations.length !== spatialRank) {
|
||||
throw new Error(`dilations should be ${spatialRank}D`);
|
||||
}
|
||||
|
||||
// Wrong strides dimension
|
||||
if (attributes.strides.length !== spatialRank) {
|
||||
throw new Error(`strides should be ${spatialRank}D`);
|
||||
}
|
||||
|
||||
// Wrong pads dimension
|
||||
if (attributes.pads.length !== spatialRank * 2) {
|
||||
throw new Error(`pads should be ${spatialRank * 2}D`);
|
||||
}
|
||||
|
||||
// Wrong output padding dimension
|
||||
if (attributes.outputPadding.length !== spatialRank) {
|
||||
throw new Error(`output_padding should be ${spatialRank}D`);
|
||||
}
|
||||
|
||||
// if kernelShape is specified, it's data length must be 2 less than dims length of the weights tensor
|
||||
// (the first 2 dims are batch_size and channels)
|
||||
if (attributes.kernelShape.length !== 0 && attributes.kernelShape.length !== inputs[1].dims.length - 2) {
|
||||
throw new Error('invalid kernel shape');
|
||||
}
|
||||
|
||||
// as with kernelShape, must have same number of spatial dims as input
|
||||
if (attributes.outputShape.length !== 0 && attributes.outputShape.length !== inputs[0].dims.length - 2) {
|
||||
throw new Error('invalid output shape');
|
||||
}
|
||||
|
||||
// TODO : Need to add support for float64
|
||||
if (inputs[0].type !== 'float32' || inputs[1].type !== 'float32') {
|
||||
throw new Error('ConvTranspose input(X,W) should be float tensor');
|
||||
}
|
||||
|
||||
if (inputs.length === 3 && inputs[2].type !== 'float32') {
|
||||
throw new Error('ConvTranspose input(bias) should be float tensor');
|
||||
}
|
||||
};
|
||||
143
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/conv.js
generated
vendored
Normal file
143
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/conv.js
generated
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.parseConvAttributes = exports.conv = exports.calculateOutputShape = void 0;
|
||||
const attribute_with_cache_key_1 = require("../../../attribute-with-cache-key");
|
||||
const util_1 = require("../../../util");
|
||||
const conv_grouped_1 = require("./conv-grouped");
|
||||
const conv_pack_1 = require("./conv-pack");
|
||||
const dot_product_1 = require("./dot-product");
|
||||
const fuse_utils_1 = require("./fuse-utils");
|
||||
const im2col_1 = require("./im2col");
|
||||
const matmul_1 = require("./matmul");
|
||||
const calculateOutputShape = (inputShape, kernelShape, dilations, adjustPads, strides) => {
|
||||
const batchSize = inputShape[0];
|
||||
const inputSpatialShape = inputShape.slice(2);
|
||||
const spatialRank = inputSpatialShape.length;
|
||||
const outChannels = kernelShape[0];
|
||||
const kernelSpatialShape = kernelShape.slice(2);
|
||||
const dilatedKernelShape = kernelSpatialShape.map((v, i) => v + (v - 1) * (dilations[i] - 1));
|
||||
const inputSpatialShapeWithPad = inputSpatialShape.map((v, i) => v + adjustPads[i] + adjustPads[i + spatialRank]);
|
||||
const outputSpatialShape = inputSpatialShapeWithPad.map((v, i) => Math.floor((v - dilatedKernelShape[i] + strides[i]) / strides[i]));
|
||||
const outputShape = [batchSize, outChannels].concat(...outputSpatialShape);
|
||||
return outputShape;
|
||||
};
|
||||
exports.calculateOutputShape = calculateOutputShape;
|
||||
const conv = (inferenceHandler, inputs, attributes) => {
|
||||
validateInputs(inputs, attributes); // currently will fail if not conv2D
|
||||
return conv2d(inferenceHandler, inputs, attributes);
|
||||
};
|
||||
exports.conv = conv;
|
||||
const conv2d = (inferenceHandler, inputs, attributes) => {
|
||||
const adjustedAttributes = getAdjustedConvAttributes(attributes, inputs);
|
||||
const packMode = inferenceHandler.session.pack;
|
||||
const isPointwise = adjustedAttributes.kernelShape[0] === 1 && adjustedAttributes.kernelShape[1] === 1;
|
||||
if (adjustedAttributes.group > 1) {
|
||||
const result = inferenceHandler.run((0, conv_grouped_1.createUnpackedGroupedConvProgramInfoLoader)(inferenceHandler, inputs, adjustedAttributes), inputs);
|
||||
return [result];
|
||||
}
|
||||
else if (isPointwise && packMode) {
|
||||
return [conv2DUnpackedPointwise(inferenceHandler, inputs, adjustedAttributes)];
|
||||
}
|
||||
else if (packMode && inputs[0].dims.length === 4 && inputs[0].dims[0] === 1 && !isPointwise) {
|
||||
return [(0, conv_pack_1.conv2DPacked)(inferenceHandler, inputs, adjustedAttributes)];
|
||||
}
|
||||
else {
|
||||
return [conv2DUnpacked(inferenceHandler, inputs, adjustedAttributes)];
|
||||
}
|
||||
};
|
||||
const conv2DUnpackedPointwise = (inferenceHandler, inputs, attributes) => {
|
||||
const xshape = inputs[0].dims;
|
||||
const kshape = inputs[1].dims;
|
||||
const outputShape = (0, exports.calculateOutputShape)(xshape, kshape, attributes.dilations, attributes.pads, attributes.strides);
|
||||
const reshapedX = inferenceHandler.reshapeUnpacked(inputs[0], [xshape[1], xshape[2] * xshape[3]]);
|
||||
const reshapedK = inferenceHandler.reshapeUnpacked(inputs[1], [kshape[0], kshape[1]]);
|
||||
const matmulInputs = inputs.length > 2 ? [reshapedK, reshapedX, inputs[2]] : [reshapedK, reshapedX];
|
||||
const matmulOutput = inferenceHandler.run((0, matmul_1.createMatmulProgramInfoLoader)(matmulInputs, attributes), matmulInputs);
|
||||
return inferenceHandler.reshapeUnpacked(matmulOutput, outputShape);
|
||||
};
|
||||
const conv2DUnpacked = (inferenceHandler, inputs, attributes) => {
|
||||
const xshape = inputs[0].dims;
|
||||
const kshape = inputs[1].dims;
|
||||
const outputShape = (0, exports.calculateOutputShape)(xshape, kshape, attributes.dilations, attributes.pads, attributes.strides);
|
||||
const xIm2Col = inferenceHandler.run((0, im2col_1.createIm2ColProgramInfoLoader)(inferenceHandler, inputs[0], inputs[1], outputShape, attributes), [inputs[0]]);
|
||||
const dotProductInputs = inputs.length === 3 ? [xIm2Col, inputs[1], inputs[2]] : [xIm2Col, inputs[1]];
|
||||
const output = inferenceHandler.run((0, dot_product_1.createDotProductProgramInfoLoader)(inferenceHandler, inputs, outputShape, attributes), dotProductInputs);
|
||||
return output;
|
||||
};
|
||||
const getAdjustedConvAttributes = (attributes, inputs) => {
|
||||
const kernelShape = attributes.kernelShape.slice();
|
||||
// if kernelShape is not specified in the attributes of this op, infer it from the weight tensor dims
|
||||
if (attributes.kernelShape.length === 0) {
|
||||
for (let i = 2; i < inputs[1].dims.length; ++i) {
|
||||
kernelShape.push(inputs[1].dims[i]);
|
||||
}
|
||||
}
|
||||
const pads = attributes.pads.slice();
|
||||
util_1.PoolConvUtil.adjustPadsBasedOnAutoPad(inputs[0].dims, attributes.strides, attributes.dilations, kernelShape, pads, attributes.autoPad);
|
||||
// always return a new object so does not modify the original attributes
|
||||
const newAttributes = Object.assign({}, attributes);
|
||||
Object.assign(newAttributes, { kernelShape, pads, cacheKey: attributes.cacheKey });
|
||||
return newAttributes;
|
||||
};
|
||||
const parseConvAttributes = (node) => {
|
||||
const attributes = node.attributes;
|
||||
const activationAttributes = (0, fuse_utils_1.parseInternalActivationAttributes)(attributes);
|
||||
// TODO : Make this generic enough to compute default attributes for multi-dimensional conv
|
||||
const autoPad = attributes.getString('auto_pad', 'NOTSET');
|
||||
const dilations = attributes.getInts('dilations', [1, 1]);
|
||||
const group = attributes.getInt('group', 1);
|
||||
const kernelShape = attributes.getInts('kernel_shape', []);
|
||||
const pads = attributes.getInts('pads', [0, 0, 0, 0]);
|
||||
const strides = attributes.getInts('strides', [1, 1]);
|
||||
return (0, attribute_with_cache_key_1.createAttributeWithCacheKey)(Object.assign({ autoPad, dilations, group, kernelShape, pads, strides }, activationAttributes));
|
||||
};
|
||||
exports.parseConvAttributes = parseConvAttributes;
|
||||
const validateInputs = (inputs, attributes) => {
|
||||
// Refer to the below link for all input checks
|
||||
// https://github.com/onnx/onnx/blob/main/docs/Operators.md#Conv
|
||||
if (!inputs || (inputs.length !== 2 && inputs.length !== 3)) {
|
||||
throw new Error('Conv requires 2 or 3 inputs');
|
||||
}
|
||||
// TODO : Need to add support for multi-dimensional conv
|
||||
if (inputs[0].dims.length !== 4 || inputs[1].dims.length !== 4) {
|
||||
throw new Error('currently only support 2-dimensional conv');
|
||||
}
|
||||
// FILTER_IN_CHANNEL should be equal to DATA_CHANNEL
|
||||
const dataChannel = inputs[0].dims[1];
|
||||
const filterInChannel = inputs[1].dims[1] * attributes.group;
|
||||
if (dataChannel !== filterInChannel) {
|
||||
throw new Error('FILTER_IN_CHANNEL should be equal to DATA_CHANNEL');
|
||||
}
|
||||
// if bias is provided it should be 1D and the number of elements should be equal to the number of feature maps
|
||||
if (inputs.length === 3 && (inputs[2].dims.length !== 1 || inputs[1].dims[0] !== inputs[2].dims[0])) {
|
||||
throw new Error('invalid bias');
|
||||
}
|
||||
const spatialRank = inputs[0].dims.length - 2;
|
||||
// wrong dilations dimension
|
||||
if (attributes.dilations.length !== spatialRank) {
|
||||
throw new Error(`dilations should be ${spatialRank}D`);
|
||||
}
|
||||
// Wrong strides dimension
|
||||
if (attributes.strides.length !== spatialRank) {
|
||||
throw new Error(`strides should be ${spatialRank}D`);
|
||||
}
|
||||
// Wrong pads dimension
|
||||
if (attributes.pads.length !== spatialRank * 2) {
|
||||
throw new Error(`pads should be ${spatialRank * 2}D`);
|
||||
}
|
||||
// if kernelShape is specified, it's data length must be 2 less than dims length of the weights tensor
|
||||
// (the first 2 dims are batch_size and channels)
|
||||
if (attributes.kernelShape.length !== 0 && attributes.kernelShape.length !== inputs[1].dims.length - 2) {
|
||||
throw new Error('invalid kernel shape');
|
||||
}
|
||||
// TODO : Need to add support for float64
|
||||
if (inputs[0].type !== 'float32' || inputs[1].type !== 'float32') {
|
||||
throw new Error('Conv input(X,W) should be float tensor');
|
||||
}
|
||||
if (inputs.length === 3 && inputs[2].type !== 'float32') {
|
||||
throw new Error('Conv input(bias) should be float tensor');
|
||||
}
|
||||
};
|
||||
//# sourceMappingURL=conv.js.map
|
||||
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/conv.js.map
generated
vendored
Normal file
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/conv.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
184
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/conv.ts
generated
vendored
Normal file
184
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/conv.ts
generated
vendored
Normal file
@@ -0,0 +1,184 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../../../attribute-with-cache-key';
|
||||
import {InferenceHandler} from '../../../backend';
|
||||
import {Graph} from '../../../graph';
|
||||
import {OperatorImplementation, OperatorInitialization} from '../../../operators';
|
||||
import {Tensor} from '../../../tensor';
|
||||
import {PoolConvUtil} from '../../../util';
|
||||
import {WebGLInferenceHandler} from '../inference-handler';
|
||||
|
||||
import {createUnpackedGroupedConvProgramInfoLoader} from './conv-grouped';
|
||||
import {conv2DPacked} from './conv-pack';
|
||||
import {createDotProductProgramInfoLoader} from './dot-product';
|
||||
import {InternalActivationAttributes, parseInternalActivationAttributes} from './fuse-utils';
|
||||
import {createIm2ColProgramInfoLoader} from './im2col';
|
||||
import {createMatmulProgramInfoLoader} from './matmul';
|
||||
|
||||
|
||||
export const calculateOutputShape =
|
||||
(inputShape: readonly number[], kernelShape: readonly number[], dilations: readonly number[],
|
||||
adjustPads: readonly number[], strides: readonly number[]): number[] => {
|
||||
const batchSize = inputShape[0];
|
||||
const inputSpatialShape = inputShape.slice(2);
|
||||
const spatialRank = inputSpatialShape.length;
|
||||
const outChannels = kernelShape[0];
|
||||
const kernelSpatialShape = kernelShape.slice(2);
|
||||
const dilatedKernelShape = kernelSpatialShape.map((v, i) => v + (v - 1) * (dilations[i] - 1));
|
||||
const inputSpatialShapeWithPad = inputSpatialShape.map((v, i) => v + adjustPads[i] + adjustPads[i + spatialRank]);
|
||||
const outputSpatialShape =
|
||||
inputSpatialShapeWithPad.map((v, i) => Math.floor((v - dilatedKernelShape[i] + strides[i]) / strides[i]));
|
||||
const outputShape = [batchSize, outChannels].concat(...outputSpatialShape);
|
||||
return outputShape;
|
||||
};
|
||||
|
||||
export interface ConvAttributes extends InternalActivationAttributes, AttributeWithCacheKey {
|
||||
readonly autoPad: string;
|
||||
readonly dilations: readonly number[];
|
||||
readonly group: number;
|
||||
readonly kernelShape: readonly number[];
|
||||
readonly pads: readonly number[];
|
||||
readonly strides: readonly number[];
|
||||
}
|
||||
|
||||
export const conv: OperatorImplementation<ConvAttributes> =
|
||||
(inferenceHandler: InferenceHandler, inputs: Tensor[], attributes: ConvAttributes): Tensor[] => {
|
||||
validateInputs(inputs, attributes); // currently will fail if not conv2D
|
||||
return conv2d(inferenceHandler, inputs, attributes);
|
||||
};
|
||||
|
||||
const conv2d: OperatorImplementation<ConvAttributes> =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: ConvAttributes): Tensor[] => {
|
||||
const adjustedAttributes = getAdjustedConvAttributes(attributes, inputs);
|
||||
const packMode = inferenceHandler.session.pack;
|
||||
const isPointwise = adjustedAttributes.kernelShape[0] === 1 && adjustedAttributes.kernelShape[1] === 1;
|
||||
if (adjustedAttributes.group > 1) {
|
||||
const result = inferenceHandler.run(
|
||||
createUnpackedGroupedConvProgramInfoLoader(inferenceHandler, inputs, adjustedAttributes), inputs);
|
||||
return [result];
|
||||
} else if (isPointwise && packMode) {
|
||||
return [conv2DUnpackedPointwise(inferenceHandler, inputs, adjustedAttributes)];
|
||||
} else if (packMode && inputs[0].dims.length === 4 && inputs[0].dims[0] === 1 && !isPointwise) {
|
||||
return [conv2DPacked(inferenceHandler, inputs, adjustedAttributes)];
|
||||
} else {
|
||||
return [conv2DUnpacked(inferenceHandler, inputs, adjustedAttributes)];
|
||||
}
|
||||
};
|
||||
|
||||
const conv2DUnpackedPointwise =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: readonly Tensor[], attributes: ConvAttributes): Tensor => {
|
||||
const xshape = inputs[0].dims;
|
||||
const kshape = inputs[1].dims;
|
||||
const outputShape =
|
||||
calculateOutputShape(xshape, kshape, attributes.dilations, attributes.pads, attributes.strides);
|
||||
const reshapedX = inferenceHandler.reshapeUnpacked(inputs[0], [xshape[1], xshape[2] * xshape[3]]);
|
||||
const reshapedK = inferenceHandler.reshapeUnpacked(inputs[1], [kshape[0], kshape[1]]);
|
||||
|
||||
const matmulInputs = inputs.length > 2 ? [reshapedK, reshapedX, inputs[2]] : [reshapedK, reshapedX];
|
||||
const matmulOutput = inferenceHandler.run(createMatmulProgramInfoLoader(matmulInputs, attributes), matmulInputs);
|
||||
return inferenceHandler.reshapeUnpacked(matmulOutput, outputShape);
|
||||
};
|
||||
|
||||
const conv2DUnpacked =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: readonly Tensor[], attributes: ConvAttributes): Tensor => {
|
||||
const xshape = inputs[0].dims;
|
||||
const kshape = inputs[1].dims;
|
||||
const outputShape =
|
||||
calculateOutputShape(xshape, kshape, attributes.dilations, attributes.pads, attributes.strides);
|
||||
const xIm2Col = inferenceHandler.run(
|
||||
createIm2ColProgramInfoLoader(inferenceHandler, inputs[0], inputs[1], outputShape, attributes), [inputs[0]]);
|
||||
|
||||
const dotProductInputs = inputs.length === 3 ? [xIm2Col, inputs[1], inputs[2]] : [xIm2Col, inputs[1]];
|
||||
const output = inferenceHandler.run(
|
||||
createDotProductProgramInfoLoader(inferenceHandler, inputs, outputShape, attributes), dotProductInputs);
|
||||
return output;
|
||||
};
|
||||
|
||||
const getAdjustedConvAttributes = <T extends ConvAttributes>(attributes: T, inputs: Tensor[]): T => {
|
||||
const kernelShape = attributes.kernelShape.slice();
|
||||
// if kernelShape is not specified in the attributes of this op, infer it from the weight tensor dims
|
||||
if (attributes.kernelShape.length === 0) {
|
||||
for (let i = 2; i < inputs[1].dims.length; ++i) {
|
||||
kernelShape.push(inputs[1].dims[i]);
|
||||
}
|
||||
}
|
||||
const pads = attributes.pads.slice();
|
||||
PoolConvUtil.adjustPadsBasedOnAutoPad(
|
||||
inputs[0].dims, attributes.strides, attributes.dilations, kernelShape, pads, attributes.autoPad);
|
||||
|
||||
// always return a new object so does not modify the original attributes
|
||||
const newAttributes: T = Object.assign({}, attributes);
|
||||
Object.assign(newAttributes, {kernelShape, pads, cacheKey: attributes.cacheKey});
|
||||
return newAttributes;
|
||||
};
|
||||
|
||||
export const parseConvAttributes: OperatorInitialization<ConvAttributes> = (node: Graph.Node): ConvAttributes => {
|
||||
const attributes = node.attributes;
|
||||
const activationAttributes = parseInternalActivationAttributes(attributes);
|
||||
// TODO : Make this generic enough to compute default attributes for multi-dimensional conv
|
||||
const autoPad = attributes.getString('auto_pad', 'NOTSET');
|
||||
const dilations = attributes.getInts('dilations', [1, 1]);
|
||||
const group = attributes.getInt('group', 1);
|
||||
const kernelShape = attributes.getInts('kernel_shape', []);
|
||||
const pads = attributes.getInts('pads', [0, 0, 0, 0]);
|
||||
const strides = attributes.getInts('strides', [1, 1]);
|
||||
|
||||
return createAttributeWithCacheKey({autoPad, dilations, group, kernelShape, pads, strides, ...activationAttributes});
|
||||
};
|
||||
|
||||
const validateInputs = (inputs: Tensor[], attributes: ConvAttributes): void => {
|
||||
// Refer to the below link for all input checks
|
||||
// https://github.com/onnx/onnx/blob/main/docs/Operators.md#Conv
|
||||
if (!inputs || (inputs.length !== 2 && inputs.length !== 3)) {
|
||||
throw new Error('Conv requires 2 or 3 inputs');
|
||||
}
|
||||
|
||||
// TODO : Need to add support for multi-dimensional conv
|
||||
if (inputs[0].dims.length !== 4 || inputs[1].dims.length !== 4) {
|
||||
throw new Error('currently only support 2-dimensional conv');
|
||||
}
|
||||
|
||||
// FILTER_IN_CHANNEL should be equal to DATA_CHANNEL
|
||||
const dataChannel = inputs[0].dims[1];
|
||||
const filterInChannel = inputs[1].dims[1] * attributes.group;
|
||||
if (dataChannel !== filterInChannel) {
|
||||
throw new Error('FILTER_IN_CHANNEL should be equal to DATA_CHANNEL');
|
||||
}
|
||||
|
||||
// if bias is provided it should be 1D and the number of elements should be equal to the number of feature maps
|
||||
if (inputs.length === 3 && (inputs[2].dims.length !== 1 || inputs[1].dims[0] !== inputs[2].dims[0])) {
|
||||
throw new Error('invalid bias');
|
||||
}
|
||||
|
||||
const spatialRank = inputs[0].dims.length - 2;
|
||||
// wrong dilations dimension
|
||||
if (attributes.dilations.length !== spatialRank) {
|
||||
throw new Error(`dilations should be ${spatialRank}D`);
|
||||
}
|
||||
|
||||
// Wrong strides dimension
|
||||
if (attributes.strides.length !== spatialRank) {
|
||||
throw new Error(`strides should be ${spatialRank}D`);
|
||||
}
|
||||
|
||||
// Wrong pads dimension
|
||||
if (attributes.pads.length !== spatialRank * 2) {
|
||||
throw new Error(`pads should be ${spatialRank * 2}D`);
|
||||
}
|
||||
|
||||
// if kernelShape is specified, it's data length must be 2 less than dims length of the weights tensor
|
||||
// (the first 2 dims are batch_size and channels)
|
||||
if (attributes.kernelShape.length !== 0 && attributes.kernelShape.length !== inputs[1].dims.length - 2) {
|
||||
throw new Error('invalid kernel shape');
|
||||
}
|
||||
|
||||
// TODO : Need to add support for float64
|
||||
if (inputs[0].type !== 'float32' || inputs[1].type !== 'float32') {
|
||||
throw new Error('Conv input(X,W) should be float tensor');
|
||||
}
|
||||
|
||||
if (inputs.length === 3 && inputs[2].type !== 'float32') {
|
||||
throw new Error('Conv input(bias) should be float tensor');
|
||||
}
|
||||
};
|
||||
62
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/depth-to-space.js
generated
vendored
Normal file
62
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/depth-to-space.js
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.parseDepthToSpaceAttributes = exports.depthToSpace = void 0;
|
||||
const transpose_1 = require("./transpose");
|
||||
const depthToSpace = (inferenceHandler, inputs, attributes) => {
|
||||
validateInputs(inputs);
|
||||
const blocksize = attributes.blocksize;
|
||||
const blocksizeSqr = blocksize * blocksize;
|
||||
const transposePerm = attributes.mode === 'DCR' ? [0, 3, 4, 1, 5, 2] : [0, 1, 4, 2, 5, 3];
|
||||
const firstReshapeShape = attributes.mode === 'DCR' ?
|
||||
[
|
||||
inputs[0].dims[0], blocksize, blocksize, inputs[0].dims[1] / blocksizeSqr, inputs[0].dims[2],
|
||||
inputs[0].dims[3]
|
||||
] :
|
||||
[
|
||||
inputs[0].dims[0], inputs[0].dims[1] / blocksizeSqr, blocksize, blocksize, inputs[0].dims[2],
|
||||
inputs[0].dims[3]
|
||||
];
|
||||
// const transpose = new WebGLTranspose();
|
||||
// const attributes = new Attribute(undefined);
|
||||
// attributes.set('perm', 'ints', transposePerm);
|
||||
// transpose.initialize(attributes);
|
||||
// First reshape
|
||||
const firstReshapedTensor = inferenceHandler.reshapeUnpacked(inputs[0], firstReshapeShape);
|
||||
// transpose
|
||||
const transposeAttributes = { perm: transposePerm, cacheKey: `${transposePerm}` };
|
||||
const [transposeOutput] = (0, transpose_1.transpose)(inferenceHandler, [firstReshapedTensor], transposeAttributes);
|
||||
// Second reshape
|
||||
const secondReshapeShape = [
|
||||
inputs[0].dims[0], inputs[0].dims[1] / blocksizeSqr, inputs[0].dims[2] * blocksize,
|
||||
inputs[0].dims[3] * blocksize
|
||||
];
|
||||
const result = inferenceHandler.reshapeUnpacked(transposeOutput, secondReshapeShape);
|
||||
return [result];
|
||||
};
|
||||
exports.depthToSpace = depthToSpace;
|
||||
const parseDepthToSpaceAttributes = (node) => {
|
||||
// processing node attributes
|
||||
const blocksize = node.attributes.getInt('blocksize');
|
||||
if (blocksize < 1) {
|
||||
throw new Error(`blocksize must be >= 1, but got : ${blocksize} for DepthToSpace`);
|
||||
}
|
||||
const mode = node.attributes.getString('mode', 'DCR');
|
||||
if (mode !== 'DCR' && mode !== 'CRD') {
|
||||
throw new Error(`unrecognized mode: ${mode} for DepthToSpace`);
|
||||
}
|
||||
return { mode, blocksize };
|
||||
};
|
||||
exports.parseDepthToSpaceAttributes = parseDepthToSpaceAttributes;
|
||||
const validateInputs = (inputs) => {
|
||||
if (inputs.length !== 1) {
|
||||
throw new Error(`DepthToSpace expect 1 inputs, but got ${inputs.length}`);
|
||||
}
|
||||
// Input has to be a 4-D tensor
|
||||
// TODO: Support string depth-to-space.
|
||||
if (inputs[0].type === 'string' || inputs[0].dims.length !== 4) {
|
||||
throw new TypeError('DepthToSpace input should be a 4-D numeric tensor');
|
||||
}
|
||||
};
|
||||
//# sourceMappingURL=depth-to-space.js.map
|
||||
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/depth-to-space.js.map
generated
vendored
Normal file
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/depth-to-space.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"depth-to-space.js","sourceRoot":"","sources":["depth-to-space.ts"],"names":[],"mappings":";AAAA,4DAA4D;AAC5D,kCAAkC;;;AAOlC,2CAA2D;AAOpD,MAAM,YAAY,GACrB,CAAC,gBAAuC,EAAE,MAAgB,EAAE,UAAkC,EAAY,EAAE;IAC1G,cAAc,CAAC,MAAM,CAAC,CAAC;IACvB,MAAM,SAAS,GAAG,UAAU,CAAC,SAAS,CAAC;IACvC,MAAM,YAAY,GAAG,SAAS,GAAG,SAAS,CAAC;IAC3C,MAAM,aAAa,GAAG,UAAU,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAC1F,MAAM,iBAAiB,GAAG,UAAU,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC;QACjD;YACE,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;YAC5F,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;SAClB,CAAC,CAAC;QACH;YACE,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;YAC5F,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;SAClB,CAAC;IAEN,0CAA0C;IAC1C,+CAA+C;IAC/C,iDAAiD;IACjD,oCAAoC;IAEpC,gBAAgB;IAChB,MAAM,mBAAmB,GAAG,gBAAgB,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,iBAAiB,CAAC,CAAC;IAE3F,YAAY;IACZ,MAAM,mBAAmB,GAAwB,EAAC,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,GAAG,aAAa,EAAE,EAAC,CAAC;IACrG,MAAM,CAAC,eAAe,CAAC,GAAG,IAAA,qBAAS,EAAC,gBAAgB,EAAE,CAAC,mBAAmB,CAAC,EAAE,mBAAmB,CAAC,CAAC;IAElG,iBAAiB;IACjB,MAAM,kBAAkB,GAAG;QACzB,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,SAAS;QAClF,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,SAAS;KAC9B,CAAC;IACF,MAAM,MAAM,GAAG,gBAAgB,CAAC,eAAe,CAAC,eAAe,EAAE,kBAAkB,CAAC,CAAC;IACrF,OAAO,CAAC,MAAM,CAAC,CAAC;AAClB,CAAC,CAAC;AAnCO,QAAA,YAAY,gBAmCnB;AAEC,MAAM,2BAA2B,GACpC,CAAC,IAAgB,EAA0B,EAAE;IAC3C,6BAA6B;IAC7B,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IACtD,IAAI,SAAS,GAAG,CAAC,EAAE;QACjB,MAAM,IAAI,KAAK,CAAC,qCAAqC,SAAS,mBAAmB,CAAC,CAAC;KACpF;IACD,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACtD,IAAI,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,EAAE;QACpC,MAAM,IAAI,KAAK,CAAC,sBAAsB,IAAI,mBAAmB,CAAC,CAAC;KAChE;IACD,OAAO,EAAC,IAAI,EAAE,SAAS,EAAC,CAAC;AAC3B,CAAC,CAAC;AAZO,QAAA,2BAA2B,+BAYlC;AAEN,MAAM,cAAc,GAAG,CAAC,MAAgB,EAAQ,EAAE;IAChD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE;QACvB,MAAM,IAAI,KAAK,CAAC,yCAAyC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;KAC3E;IAED,+BAA+B;IAC/B,uCAAuC;IACvC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE;QAC9D,MAAM,IAAI,SAAS,CAAC,mDAAmD,CAAC,CAAC;KAC1E;AACH,CAAC,CAAC"}
|
||||
77
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/depth-to-space.ts
generated
vendored
Normal file
77
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/depth-to-space.ts
generated
vendored
Normal file
@@ -0,0 +1,77 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import {Graph} from '../../../graph';
|
||||
import {OperatorImplementation, OperatorInitialization} from '../../../operators';
|
||||
import {Tensor} from '../../../tensor';
|
||||
import {WebGLInferenceHandler} from '../inference-handler';
|
||||
|
||||
import {transpose, TransposeAttributes} from './transpose';
|
||||
|
||||
export interface DepthToSpaceAttributes {
|
||||
mode: 'DCR'|'CRD';
|
||||
blocksize: number;
|
||||
}
|
||||
|
||||
export const depthToSpace: OperatorImplementation<DepthToSpaceAttributes> =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: DepthToSpaceAttributes): Tensor[] => {
|
||||
validateInputs(inputs);
|
||||
const blocksize = attributes.blocksize;
|
||||
const blocksizeSqr = blocksize * blocksize;
|
||||
const transposePerm = attributes.mode === 'DCR' ? [0, 3, 4, 1, 5, 2] : [0, 1, 4, 2, 5, 3];
|
||||
const firstReshapeShape = attributes.mode === 'DCR' ?
|
||||
[
|
||||
inputs[0].dims[0], blocksize, blocksize, inputs[0].dims[1] / blocksizeSqr, inputs[0].dims[2],
|
||||
inputs[0].dims[3]
|
||||
] :
|
||||
[
|
||||
inputs[0].dims[0], inputs[0].dims[1] / blocksizeSqr, blocksize, blocksize, inputs[0].dims[2],
|
||||
inputs[0].dims[3]
|
||||
];
|
||||
|
||||
// const transpose = new WebGLTranspose();
|
||||
// const attributes = new Attribute(undefined);
|
||||
// attributes.set('perm', 'ints', transposePerm);
|
||||
// transpose.initialize(attributes);
|
||||
|
||||
// First reshape
|
||||
const firstReshapedTensor = inferenceHandler.reshapeUnpacked(inputs[0], firstReshapeShape);
|
||||
|
||||
// transpose
|
||||
const transposeAttributes: TransposeAttributes = {perm: transposePerm, cacheKey: `${transposePerm}`};
|
||||
const [transposeOutput] = transpose(inferenceHandler, [firstReshapedTensor], transposeAttributes);
|
||||
|
||||
// Second reshape
|
||||
const secondReshapeShape = [
|
||||
inputs[0].dims[0], inputs[0].dims[1] / blocksizeSqr, inputs[0].dims[2] * blocksize,
|
||||
inputs[0].dims[3] * blocksize
|
||||
];
|
||||
const result = inferenceHandler.reshapeUnpacked(transposeOutput, secondReshapeShape);
|
||||
return [result];
|
||||
};
|
||||
|
||||
export const parseDepthToSpaceAttributes: OperatorInitialization<DepthToSpaceAttributes> =
|
||||
(node: Graph.Node): DepthToSpaceAttributes => {
|
||||
// processing node attributes
|
||||
const blocksize = node.attributes.getInt('blocksize');
|
||||
if (blocksize < 1) {
|
||||
throw new Error(`blocksize must be >= 1, but got : ${blocksize} for DepthToSpace`);
|
||||
}
|
||||
const mode = node.attributes.getString('mode', 'DCR');
|
||||
if (mode !== 'DCR' && mode !== 'CRD') {
|
||||
throw new Error(`unrecognized mode: ${mode} for DepthToSpace`);
|
||||
}
|
||||
return {mode, blocksize};
|
||||
};
|
||||
|
||||
const validateInputs = (inputs: Tensor[]): void => {
|
||||
if (inputs.length !== 1) {
|
||||
throw new Error(`DepthToSpace expect 1 inputs, but got ${inputs.length}`);
|
||||
}
|
||||
|
||||
// Input has to be a 4-D tensor
|
||||
// TODO: Support string depth-to-space.
|
||||
if (inputs[0].type === 'string' || inputs[0].dims.length !== 4) {
|
||||
throw new TypeError('DepthToSpace input should be a 4-D numeric tensor');
|
||||
}
|
||||
};
|
||||
60
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/dot-product.js
generated
vendored
Normal file
60
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/dot-product.js
generated
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createDotProductProgramInfoLoader = void 0;
|
||||
const util_1 = require("../../../util");
|
||||
const glsl_source_1 = require("../glsl-source");
|
||||
const types_1 = require("../types");
|
||||
const fuse_utils_1 = require("./fuse-utils");
|
||||
const im2col_1 = require("./im2col");
|
||||
const createDotProductProgramMetadata = (hasBias, attributes) => ({
|
||||
name: 'ConvDotProduct',
|
||||
inputNames: hasBias ? ['Im2Col', 'K', 'B'] : ['Im2Col', 'K'],
|
||||
inputTypes: hasBias ? [types_1.TextureType.unpacked, types_1.TextureType.packedLastDimension, types_1.TextureType.unpacked] :
|
||||
[types_1.TextureType.unpacked, types_1.TextureType.packedLastDimension],
|
||||
cacheKey: attributes.activationCacheKey
|
||||
});
|
||||
const createDotProductProgramInfo = (inferenceHandler, metadata, inputs, outputShape, attributes) => {
|
||||
const xshape = inputs[0].dims;
|
||||
const kshape = inputs[1].dims;
|
||||
const adjustedKernelShape = [kshape[0], Math.ceil((xshape[1] * kshape[2] * kshape[3]) / 4)];
|
||||
const im2colShape = (0, im2col_1.calculateIm2ColDims)(xshape, kshape, outputShape);
|
||||
const [kWidth, kHeight] = inferenceHandler.calculateTextureWidthAndHeight(adjustedKernelShape, types_1.TextureType.packedLastDimension);
|
||||
const im2colStrides = util_1.ShapeUtil.computeStrides(im2colShape);
|
||||
const [im2colWidth, im2colHeight] = inferenceHandler.calculateTextureWidthAndHeight(im2colShape, types_1.TextureType.packedLastDimension);
|
||||
const rank = outputShape.length;
|
||||
const initValue = (inputs.length < 3) ? '0.0' : '_B(b)';
|
||||
const sharedDim = Math.ceil(xshape[1] * kshape[2] * kshape[3] / 4);
|
||||
const { activationFunction, applyActivation } = (0, fuse_utils_1.getActivationSnippet)(attributes);
|
||||
const glsl = (0, glsl_source_1.getGlsl)(inferenceHandler.session.backend.glContext.version);
|
||||
const shaderSource = `
|
||||
${activationFunction}
|
||||
float process(int indices[${rank}]) {
|
||||
int b[1];
|
||||
b[0] = indices[1];
|
||||
int im2col[4];
|
||||
im2col[0] = indices[0];
|
||||
im2col[1] = indices[2];
|
||||
im2col[2] = indices[3];
|
||||
int im2colOffset = im2col[0] * ${im2colStrides[0]} + im2col[1] * ${im2colStrides[1]} + im2col[2] * ${im2colStrides[2]};
|
||||
int kernelOffset = indices[1] * ${adjustedKernelShape[1]};
|
||||
float value = ${initValue};
|
||||
for (int i = 0; i < ${sharedDim}; ++i) {
|
||||
vec2 im2colCoords = offsetToCoords(im2colOffset, ${im2colWidth}, ${im2colHeight});
|
||||
vec2 kernelCoords = offsetToCoords(kernelOffset, ${kWidth}, ${kHeight});
|
||||
value += dot(${glsl.texture2D}(Im2Col, im2colCoords), ${glsl.texture2D}(K, kernelCoords));
|
||||
++im2colOffset;
|
||||
++kernelOffset;
|
||||
}
|
||||
${applyActivation}
|
||||
return value;
|
||||
}`;
|
||||
return Object.assign(Object.assign({}, metadata), { output: { dims: outputShape, type: inputs[0].type, textureType: types_1.TextureType.unpacked }, shaderSource });
|
||||
};
|
||||
const createDotProductProgramInfoLoader = (inferenceHandler, inputs, outputShape, attributes) => {
|
||||
const metadata = createDotProductProgramMetadata(inputs.length > 2, attributes);
|
||||
return Object.assign(Object.assign({}, metadata), { get: () => createDotProductProgramInfo(inferenceHandler, metadata, inputs, outputShape, attributes) });
|
||||
};
|
||||
exports.createDotProductProgramInfoLoader = createDotProductProgramInfoLoader;
|
||||
//# sourceMappingURL=dot-product.js.map
|
||||
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/dot-product.js.map
generated
vendored
Normal file
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/dot-product.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"dot-product.js","sourceRoot":"","sources":["dot-product.ts"],"names":[],"mappings":"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"}
|
||||
78
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/dot-product.ts
generated
vendored
Normal file
78
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/dot-product.ts
generated
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import {Tensor} from '../../../tensor';
|
||||
import {ShapeUtil} from '../../../util';
|
||||
import {getGlsl} from '../glsl-source';
|
||||
import {WebGLInferenceHandler} from '../inference-handler';
|
||||
import {ProgramInfo, ProgramInfoLoader, ProgramMetadata, TextureType} from '../types';
|
||||
|
||||
import {getActivationSnippet, InternalActivationAttributes} from './fuse-utils';
|
||||
import {calculateIm2ColDims} from './im2col';
|
||||
|
||||
const createDotProductProgramMetadata = (hasBias: boolean, attributes: InternalActivationAttributes) => ({
|
||||
name: 'ConvDotProduct',
|
||||
inputNames: hasBias ? ['Im2Col', 'K', 'B'] : ['Im2Col', 'K'],
|
||||
inputTypes: hasBias ? [TextureType.unpacked, TextureType.packedLastDimension, TextureType.unpacked] :
|
||||
[TextureType.unpacked, TextureType.packedLastDimension],
|
||||
cacheKey: attributes.activationCacheKey
|
||||
});
|
||||
|
||||
const createDotProductProgramInfo =
|
||||
(inferenceHandler: WebGLInferenceHandler, metadata: ProgramMetadata, inputs: readonly Tensor[],
|
||||
outputShape: number[], attributes: InternalActivationAttributes): ProgramInfo => {
|
||||
const xshape = inputs[0].dims;
|
||||
const kshape = inputs[1].dims;
|
||||
const adjustedKernelShape = [kshape[0], Math.ceil((xshape[1] * kshape[2] * kshape[3]) / 4)];
|
||||
const im2colShape = calculateIm2ColDims(xshape, kshape, outputShape);
|
||||
const [kWidth, kHeight] =
|
||||
inferenceHandler.calculateTextureWidthAndHeight(adjustedKernelShape, TextureType.packedLastDimension);
|
||||
|
||||
const im2colStrides = ShapeUtil.computeStrides(im2colShape);
|
||||
const [im2colWidth, im2colHeight] =
|
||||
inferenceHandler.calculateTextureWidthAndHeight(im2colShape, TextureType.packedLastDimension);
|
||||
const rank = outputShape.length;
|
||||
|
||||
const initValue = (inputs.length < 3) ? '0.0' : '_B(b)';
|
||||
const sharedDim = Math.ceil(xshape[1] * kshape[2] * kshape[3] / 4);
|
||||
const {activationFunction, applyActivation} = getActivationSnippet(attributes);
|
||||
const glsl = getGlsl(inferenceHandler.session.backend.glContext.version);
|
||||
const shaderSource = `
|
||||
${activationFunction}
|
||||
float process(int indices[${rank}]) {
|
||||
int b[1];
|
||||
b[0] = indices[1];
|
||||
int im2col[4];
|
||||
im2col[0] = indices[0];
|
||||
im2col[1] = indices[2];
|
||||
im2col[2] = indices[3];
|
||||
int im2colOffset = im2col[0] * ${im2colStrides[0]} + im2col[1] * ${im2colStrides[1]} + im2col[2] * ${
|
||||
im2colStrides[2]};
|
||||
int kernelOffset = indices[1] * ${adjustedKernelShape[1]};
|
||||
float value = ${initValue};
|
||||
for (int i = 0; i < ${sharedDim}; ++i) {
|
||||
vec2 im2colCoords = offsetToCoords(im2colOffset, ${im2colWidth}, ${im2colHeight});
|
||||
vec2 kernelCoords = offsetToCoords(kernelOffset, ${kWidth}, ${kHeight});
|
||||
value += dot(${glsl.texture2D}(Im2Col, im2colCoords), ${glsl.texture2D}(K, kernelCoords));
|
||||
++im2colOffset;
|
||||
++kernelOffset;
|
||||
}
|
||||
${applyActivation}
|
||||
return value;
|
||||
}`;
|
||||
return {
|
||||
...metadata,
|
||||
output: {dims: outputShape, type: inputs[0].type, textureType: TextureType.unpacked},
|
||||
shaderSource
|
||||
};
|
||||
};
|
||||
|
||||
export const createDotProductProgramInfoLoader =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: readonly Tensor[], outputShape: number[],
|
||||
attributes: InternalActivationAttributes): ProgramInfoLoader => {
|
||||
const metadata = createDotProductProgramMetadata(inputs.length > 2, attributes);
|
||||
return {
|
||||
...metadata,
|
||||
get: () => createDotProductProgramInfo(inferenceHandler, metadata, inputs, outputShape, attributes)
|
||||
};
|
||||
};
|
||||
31
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/flatten.js
generated
vendored
Normal file
31
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/flatten.js
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.parseFlattenAttributes = exports.flatten = void 0;
|
||||
const util_1 = require("../../../util");
|
||||
const flatten = (inferenceHandler, inputs, axis) => {
|
||||
validateInputs(inputs, axis);
|
||||
const outputDims = util_1.ShapeUtil.flattenShape(inputs[0].dims, axis);
|
||||
return [inferenceHandler.reshapeUnpacked(inputs[0], outputDims)];
|
||||
};
|
||||
exports.flatten = flatten;
|
||||
const parseFlattenAttributes = (node) => node.attributes.getInt('axis', 1); // default axis is 1
|
||||
exports.parseFlattenAttributes = parseFlattenAttributes;
|
||||
const validateInputs = (inputs, axis) => {
|
||||
if (!inputs || inputs.length !== 1) {
|
||||
throw new Error('Flatten requires 1 input.');
|
||||
}
|
||||
const r = inputs[0].dims.length;
|
||||
if (r === 0) {
|
||||
throw new Error('scalar tensor is not supported.');
|
||||
}
|
||||
if (axis < -r || axis > r) {
|
||||
throw new Error('Invalid axis');
|
||||
}
|
||||
// TODO: Support string type
|
||||
if (inputs[0].type === 'string') {
|
||||
throw new Error('string tensor is not supported.');
|
||||
}
|
||||
};
|
||||
//# sourceMappingURL=flatten.js.map
|
||||
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/flatten.js.map
generated
vendored
Normal file
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/flatten.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"flatten.js","sourceRoot":"","sources":["flatten.ts"],"names":[],"mappings":";AAAA,4DAA4D;AAC5D,kCAAkC;;;AAKlC,wCAAwC;AAGjC,MAAM,OAAO,GAChB,CAAC,gBAAuC,EAAE,MAAgB,EAAE,IAAY,EAAY,EAAE;IACpF,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAE7B,MAAM,UAAU,GAAG,gBAAS,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAChE,OAAO,CAAC,gBAAgB,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC;AACnE,CAAC,CAAC;AANO,QAAA,OAAO,WAMd;AAEC,MAAM,sBAAsB,GAAmC,CAAC,IAAgB,EAAU,EAAE,CAC/F,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAE,oBAAoB;AAD/C,QAAA,sBAAsB,0BACG;AAEtC,MAAM,cAAc,GAAG,CAAC,MAAgB,EAAE,IAAY,EAAQ,EAAE;IAC9D,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE;QAClC,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;KAC9C;IAED,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;IAChC,IAAI,CAAC,KAAK,CAAC,EAAE;QACX,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;KACpD;IAED,IAAI,IAAI,GAAG,CAAC,CAAC,IAAI,IAAI,GAAG,CAAC,EAAE;QACzB,MAAM,IAAI,KAAK,CAAC,cAAc,CAAC,CAAC;KACjC;IAED,4BAA4B;IAC5B,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,EAAE;QAC/B,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;KACpD;AACH,CAAC,CAAC"}
|
||||
39
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/flatten.ts
generated
vendored
Normal file
39
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/flatten.ts
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import {Graph} from '../../../graph';
|
||||
import {OperatorImplementation, OperatorInitialization} from '../../../operators';
|
||||
import {Tensor} from '../../../tensor';
|
||||
import {ShapeUtil} from '../../../util';
|
||||
import {WebGLInferenceHandler} from '../inference-handler';
|
||||
|
||||
export const flatten: OperatorImplementation<number> =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], axis: number): Tensor[] => {
|
||||
validateInputs(inputs, axis);
|
||||
|
||||
const outputDims = ShapeUtil.flattenShape(inputs[0].dims, axis);
|
||||
return [inferenceHandler.reshapeUnpacked(inputs[0], outputDims)];
|
||||
};
|
||||
|
||||
export const parseFlattenAttributes: OperatorInitialization<number> = (node: Graph.Node): number =>
|
||||
node.attributes.getInt('axis', 1); // default axis is 1
|
||||
|
||||
const validateInputs = (inputs: Tensor[], axis: number): void => {
|
||||
if (!inputs || inputs.length !== 1) {
|
||||
throw new Error('Flatten requires 1 input.');
|
||||
}
|
||||
|
||||
const r = inputs[0].dims.length;
|
||||
if (r === 0) {
|
||||
throw new Error('scalar tensor is not supported.');
|
||||
}
|
||||
|
||||
if (axis < -r || axis > r) {
|
||||
throw new Error('Invalid axis');
|
||||
}
|
||||
|
||||
// TODO: Support string type
|
||||
if (inputs[0].type === 'string') {
|
||||
throw new Error('string tensor is not supported.');
|
||||
}
|
||||
};
|
||||
39
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/fuse-utils.js
generated
vendored
Normal file
39
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/fuse-utils.js
generated
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.parseInternalActivationAttributes = exports.getActivationSnippet = void 0;
|
||||
const util_1 = require("../../../util");
|
||||
const unary_op_1 = require("./unary-op");
|
||||
function getActivationSnippet(attributes) {
|
||||
let func;
|
||||
switch (attributes.activation) {
|
||||
case 'Relu':
|
||||
func = (0, unary_op_1.glslRelu)();
|
||||
break;
|
||||
case 'Sigmoid':
|
||||
func = (0, unary_op_1.glslSigmoid)();
|
||||
break;
|
||||
case 'Clip':
|
||||
func = (0, unary_op_1.glslClip)(attributes.clipMin, attributes.clipMax);
|
||||
break;
|
||||
// TODO: adding other activations that can be fused.
|
||||
default:
|
||||
return { activationFunction: '', applyActivation: '' };
|
||||
}
|
||||
const activationName = func.name;
|
||||
const activationFunction = func.body;
|
||||
const applyActivation = `value = ${activationName}_(value);`;
|
||||
return { activationFunction, applyActivation };
|
||||
}
|
||||
exports.getActivationSnippet = getActivationSnippet;
|
||||
const parseInternalActivationAttributes = (attributes) => {
|
||||
const activation = attributes.getString('activation', '');
|
||||
if (activation === 'Clip') {
|
||||
const [clipMin, clipMax] = attributes.getFloats('activation_params', [util_1.MIN_CLIP, util_1.MAX_CLIP]);
|
||||
return { activation, clipMax, clipMin, activationCacheKey: `${activation}:${clipMin},${clipMax}` };
|
||||
}
|
||||
return { activation, activationCacheKey: activation };
|
||||
};
|
||||
exports.parseInternalActivationAttributes = parseInternalActivationAttributes;
|
||||
//# sourceMappingURL=fuse-utils.js.map
|
||||
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/fuse-utils.js.map
generated
vendored
Normal file
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/fuse-utils.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"fuse-utils.js","sourceRoot":"","sources":["fuse-utils.ts"],"names":[],"mappings":";AAAA,4DAA4D;AAC5D,kCAAkC;;;AAGlC,wCAAiD;AAGjD,yCAA2D;AAS3D,SAAgB,oBAAoB,CAAC,UAAwC;IAC3E,IAAI,IAAuB,CAAC;IAC5B,QAAQ,UAAU,CAAC,UAAU,EAAE;QAC7B,KAAK,MAAM;YACT,IAAI,GAAG,IAAA,mBAAQ,GAAE,CAAC;YAClB,MAAM;QACR,KAAK,SAAS;YACZ,IAAI,GAAG,IAAA,sBAAW,GAAE,CAAC;YACrB,MAAM;QACR,KAAK,MAAM;YACT,IAAI,GAAG,IAAA,mBAAQ,EAAC,UAAU,CAAC,OAAQ,EAAE,UAAU,CAAC,OAAQ,CAAC,CAAC;YAC1D,MAAM;QACR,oDAAoD;QACpD;YACE,OAAO,EAAC,kBAAkB,EAAE,EAAE,EAAE,eAAe,EAAE,EAAE,EAAC,CAAC;KACxD;IAED,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC;IACjC,MAAM,kBAAkB,GAAG,IAAI,CAAC,IAAI,CAAC;IACrC,MAAM,eAAe,GAAG,WAAW,cAAc,WAAW,CAAC;IAC7D,OAAO,EAAC,kBAAkB,EAAE,eAAe,EAAC,CAAC;AAC/C,CAAC;AArBD,oDAqBC;AAEM,MAAM,iCAAiC,GAAG,CAAC,UAAqB,EAAgC,EAAE;IACvG,MAAM,UAAU,GAAG,UAAU,CAAC,SAAS,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;IAE1D,IAAI,UAAU,KAAK,MAAM,EAAE;QACzB,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,GAAG,UAAU,CAAC,SAAS,CAAC,mBAAmB,EAAE,CAAC,eAAQ,EAAE,eAAQ,CAAC,CAAC,CAAC;QAC3F,OAAO,EAAC,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,kBAAkB,EAAE,GAAG,UAAU,IAAI,OAAO,IAAI,OAAO,EAAE,EAAC,CAAC;KAClG;IACD,OAAO,EAAC,UAAU,EAAE,kBAAkB,EAAE,UAAU,EAAC,CAAC;AACtD,CAAC,CAAC;AARW,QAAA,iCAAiC,qCAQ5C"}
|
||||
48
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/fuse-utils.ts
generated
vendored
Normal file
48
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/fuse-utils.ts
generated
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import {Attribute} from '../../../attribute';
|
||||
import {MAX_CLIP, MIN_CLIP} from '../../../util';
|
||||
import {GlslValueFunction} from '../glsl-definitions';
|
||||
|
||||
import {glslClip, glslRelu, glslSigmoid} from './unary-op';
|
||||
|
||||
export interface InternalActivationAttributes {
|
||||
readonly activation: string;
|
||||
readonly clipMin?: number;
|
||||
readonly clipMax?: number;
|
||||
readonly activationCacheKey: string;
|
||||
}
|
||||
|
||||
export function getActivationSnippet(attributes: InternalActivationAttributes) {
|
||||
let func: GlslValueFunction;
|
||||
switch (attributes.activation) {
|
||||
case 'Relu':
|
||||
func = glslRelu();
|
||||
break;
|
||||
case 'Sigmoid':
|
||||
func = glslSigmoid();
|
||||
break;
|
||||
case 'Clip':
|
||||
func = glslClip(attributes.clipMin!, attributes.clipMax!);
|
||||
break;
|
||||
// TODO: adding other activations that can be fused.
|
||||
default:
|
||||
return {activationFunction: '', applyActivation: ''};
|
||||
}
|
||||
|
||||
const activationName = func.name;
|
||||
const activationFunction = func.body;
|
||||
const applyActivation = `value = ${activationName}_(value);`;
|
||||
return {activationFunction, applyActivation};
|
||||
}
|
||||
|
||||
export const parseInternalActivationAttributes = (attributes: Attribute): InternalActivationAttributes => {
|
||||
const activation = attributes.getString('activation', '');
|
||||
|
||||
if (activation === 'Clip') {
|
||||
const [clipMin, clipMax] = attributes.getFloats('activation_params', [MIN_CLIP, MAX_CLIP]);
|
||||
return {activation, clipMax, clipMin, activationCacheKey: `${activation}:${clipMin},${clipMax}`};
|
||||
}
|
||||
return {activation, activationCacheKey: activation};
|
||||
};
|
||||
87
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/gather.js
generated
vendored
Normal file
87
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/gather.js
generated
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.parseGatherAttributes = exports.gather = void 0;
|
||||
const attribute_with_cache_key_1 = require("../../../attribute-with-cache-key");
|
||||
const operators_1 = require("../../../operators");
|
||||
const util_1 = require("../../../util");
|
||||
const types_1 = require("../types");
|
||||
const gather = (inferenceHandler, inputs, attributes) => {
|
||||
validateInputs(inputs, attributes.axis);
|
||||
const output = inferenceHandler.run(createGatherProgramInfoLoader(inferenceHandler, inputs, attributes), inputs);
|
||||
return [output];
|
||||
};
|
||||
exports.gather = gather;
|
||||
const parseGatherAttributes = (node) => (0, attribute_with_cache_key_1.createAttributeWithCacheKey)({ axis: node.attributes.getInt('axis', 0) });
|
||||
exports.parseGatherAttributes = parseGatherAttributes;
|
||||
const gatherProgramMetadata = {
|
||||
name: 'Gather',
|
||||
inputNames: ['A', 'B'],
|
||||
inputTypes: [types_1.TextureType.unpacked, types_1.TextureType.unpacked],
|
||||
};
|
||||
const createGatherProgramInfo = (handler, metadata, inputs, axis) => {
|
||||
const inputShape = inputs[0].dims.slice();
|
||||
const indexDataShape = inputs[1].dims.slice();
|
||||
const outputShape = new Array(inputShape.length + indexDataShape.length - 1);
|
||||
axis = util_1.ShapeUtil.normalizeAxis(axis, inputShape.length);
|
||||
const indexCopyOps = [];
|
||||
for (let i = 0; i < outputShape.length; i++) {
|
||||
// outputShape is divided into three parts: A, B, C
|
||||
// |0 axis| axis + indexDataShape.length | end|
|
||||
// | A | B | C |
|
||||
//
|
||||
// inputIdx: [A, inputs[1][B], C]
|
||||
if (i < axis) { // A
|
||||
outputShape[i] = inputShape[i];
|
||||
indexCopyOps.push(`inputIdx[${i}] = outputIdx[${i}];`);
|
||||
}
|
||||
else {
|
||||
if (i < axis + indexDataShape.length) { // B
|
||||
outputShape[i] = indexDataShape[i - axis];
|
||||
indexCopyOps.push(`indexDataIdx[${i - axis}] = outputIdx[${i}];`);
|
||||
}
|
||||
else { // C
|
||||
outputShape[i] = inputShape[i - indexDataShape.length + 1]; // skip 1 for axis
|
||||
indexCopyOps.push(`inputIdx[${i - indexDataShape.length + 1}] = outputIdx[${i}];`);
|
||||
}
|
||||
}
|
||||
}
|
||||
const orank = outputShape.length || 1;
|
||||
const irank = inputShape.length;
|
||||
const iDrank = indexDataShape.length || 1;
|
||||
const shaderSource = `
|
||||
float process(int outputIdx[${orank}]) {
|
||||
int inputIdx[${irank}];
|
||||
int indexDataIdx[${iDrank}];
|
||||
indexDataIdx[0] = 0;
|
||||
${indexCopyOps.join('\n ')}
|
||||
int idx = int(_B(indexDataIdx));
|
||||
inputIdx[${axis}] = idx < 0 ? idx + ${inputShape[axis]} : idx;
|
||||
return _A(inputIdx);
|
||||
}`;
|
||||
return Object.assign(Object.assign({}, metadata), { output: { dims: outputShape, type: inputs[0].type, textureType: types_1.TextureType.unpacked }, shaderSource });
|
||||
};
|
||||
const createGatherProgramInfoLoader = (handler, inputs, attributes) => {
|
||||
const metadata = Object.assign(Object.assign({}, gatherProgramMetadata), { cacheHint: attributes.cacheKey });
|
||||
return Object.assign(Object.assign({}, metadata), { get: () => createGatherProgramInfo(handler, metadata, inputs, attributes.axis) });
|
||||
};
|
||||
const validateInputs = (inputs, axis) => {
|
||||
if (!inputs || inputs.length !== 2) {
|
||||
throw new Error('Gather requires 2 inputs.');
|
||||
}
|
||||
const tensorRank = inputs[0].dims.length;
|
||||
if (tensorRank < 1) {
|
||||
throw new Error('Invalid input shape.');
|
||||
}
|
||||
if (axis < -tensorRank || axis > tensorRank - 1) {
|
||||
throw new Error('Invalid axis.');
|
||||
}
|
||||
if (operators_1.NUMBER_TYPES.indexOf(inputs[0].type) === -1) {
|
||||
throw new Error('Invaid input type.');
|
||||
}
|
||||
if (inputs[1].type !== 'int32' && inputs[1].type !== 'int16') {
|
||||
throw new Error('Invaid input type.');
|
||||
}
|
||||
};
|
||||
//# sourceMappingURL=gather.js.map
|
||||
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/gather.js.map
generated
vendored
Normal file
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/gather.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"gather.js","sourceRoot":"","sources":["gather.ts"],"names":[],"mappings":"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"}
|
||||
103
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/gather.ts
generated
vendored
Normal file
103
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/gather.ts
generated
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../../../attribute-with-cache-key';
|
||||
import {Graph} from '../../../graph';
|
||||
import {NUMBER_TYPES, OperatorImplementation, OperatorInitialization} from '../../../operators';
|
||||
import {Tensor} from '../../../tensor';
|
||||
import {ShapeUtil} from '../../../util';
|
||||
import {WebGLInferenceHandler} from '../inference-handler';
|
||||
import {ProgramInfo, ProgramInfoLoader, ProgramMetadata, TextureType} from '../types';
|
||||
|
||||
interface GatherAttributes extends AttributeWithCacheKey {
|
||||
readonly axis: number;
|
||||
}
|
||||
|
||||
export const gather: OperatorImplementation<GatherAttributes> =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: GatherAttributes): Tensor[] => {
|
||||
validateInputs(inputs, attributes.axis);
|
||||
const output = inferenceHandler.run(createGatherProgramInfoLoader(inferenceHandler, inputs, attributes), inputs);
|
||||
return [output];
|
||||
};
|
||||
|
||||
export const parseGatherAttributes: OperatorInitialization<GatherAttributes> = (node: Graph.Node): GatherAttributes =>
|
||||
createAttributeWithCacheKey({axis: node.attributes.getInt('axis', 0)});
|
||||
|
||||
const gatherProgramMetadata = {
|
||||
name: 'Gather',
|
||||
inputNames: ['A', 'B'],
|
||||
inputTypes: [TextureType.unpacked, TextureType.unpacked],
|
||||
};
|
||||
|
||||
const createGatherProgramInfo =
|
||||
(handler: WebGLInferenceHandler, metadata: ProgramMetadata, inputs: Tensor[], axis: number): ProgramInfo => {
|
||||
const inputShape = inputs[0].dims.slice();
|
||||
const indexDataShape = inputs[1].dims.slice();
|
||||
const outputShape = new Array(inputShape.length + indexDataShape.length - 1);
|
||||
|
||||
axis = ShapeUtil.normalizeAxis(axis, inputShape.length);
|
||||
const indexCopyOps: string[] = [];
|
||||
for (let i = 0; i < outputShape.length; i++) {
|
||||
// outputShape is divided into three parts: A, B, C
|
||||
// |0 axis| axis + indexDataShape.length | end|
|
||||
// | A | B | C |
|
||||
//
|
||||
// inputIdx: [A, inputs[1][B], C]
|
||||
if (i < axis) { // A
|
||||
outputShape[i] = inputShape[i];
|
||||
indexCopyOps.push(`inputIdx[${i}] = outputIdx[${i}];`);
|
||||
} else {
|
||||
if (i < axis + indexDataShape.length) { // B
|
||||
outputShape[i] = indexDataShape[i - axis];
|
||||
indexCopyOps.push(`indexDataIdx[${i - axis}] = outputIdx[${i}];`);
|
||||
} else { // C
|
||||
outputShape[i] = inputShape[i - indexDataShape.length + 1]; // skip 1 for axis
|
||||
indexCopyOps.push(`inputIdx[${i - indexDataShape.length + 1}] = outputIdx[${i}];`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const orank = outputShape.length || 1;
|
||||
const irank = inputShape.length;
|
||||
const iDrank = indexDataShape.length || 1;
|
||||
const shaderSource = `
|
||||
float process(int outputIdx[${orank}]) {
|
||||
int inputIdx[${irank}];
|
||||
int indexDataIdx[${iDrank}];
|
||||
indexDataIdx[0] = 0;
|
||||
${indexCopyOps.join('\n ')}
|
||||
int idx = int(_B(indexDataIdx));
|
||||
inputIdx[${axis}] = idx < 0 ? idx + ${inputShape[axis]} : idx;
|
||||
return _A(inputIdx);
|
||||
}`;
|
||||
return {
|
||||
...metadata,
|
||||
output: {dims: outputShape, type: inputs[0].type, textureType: TextureType.unpacked},
|
||||
shaderSource
|
||||
};
|
||||
};
|
||||
|
||||
const createGatherProgramInfoLoader =
|
||||
(handler: WebGLInferenceHandler, inputs: Tensor[], attributes: GatherAttributes): ProgramInfoLoader => {
|
||||
const metadata = {...gatherProgramMetadata, cacheHint: attributes.cacheKey};
|
||||
return {...metadata, get: () => createGatherProgramInfo(handler, metadata, inputs, attributes.axis)};
|
||||
};
|
||||
|
||||
const validateInputs = (inputs: Tensor[], axis: number): void => {
|
||||
if (!inputs || inputs.length !== 2) {
|
||||
throw new Error('Gather requires 2 inputs.');
|
||||
}
|
||||
const tensorRank = inputs[0].dims.length;
|
||||
if (tensorRank < 1) {
|
||||
throw new Error('Invalid input shape.');
|
||||
}
|
||||
if (axis < -tensorRank || axis > tensorRank - 1) {
|
||||
throw new Error('Invalid axis.');
|
||||
}
|
||||
if (NUMBER_TYPES.indexOf(inputs[0].type) === -1) {
|
||||
throw new Error('Invaid input type.');
|
||||
}
|
||||
if (inputs[1].type !== 'int32' && inputs[1].type !== 'int16') {
|
||||
throw new Error('Invaid input type.');
|
||||
}
|
||||
};
|
||||
113
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/gemm.js
generated
vendored
Normal file
113
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/gemm.js
generated
vendored
Normal file
@@ -0,0 +1,113 @@
|
||||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.parseGemmAttributesV11 = exports.parseGemmAttributesV7 = exports.gemm = void 0;
|
||||
const attribute_with_cache_key_1 = require("../../../attribute-with-cache-key");
|
||||
const util_1 = require("../../../util");
|
||||
const types_1 = require("../types");
|
||||
const gemm = (inferenceHandler, inputs, attributes) => {
|
||||
validateInputs(inputs, attributes);
|
||||
const output = inferenceHandler.run(createGemmProgramInfoLoader(inputs, attributes), inputs);
|
||||
return [output];
|
||||
};
|
||||
exports.gemm = gemm;
|
||||
const parseGemmAttributes = (node, isOptionalC) => {
|
||||
const transA = node.attributes.getInt('transA', 0) !== 0;
|
||||
const transB = node.attributes.getInt('transB', 0) !== 0;
|
||||
const alpha = node.attributes.getFloat('alpha', 1.0);
|
||||
const beta = node.attributes.getFloat('beta', 1.0);
|
||||
return (0, attribute_with_cache_key_1.createAttributeWithCacheKey)({ transA, transB, alpha, beta, isOptionalC });
|
||||
};
|
||||
const parseGemmAttributesV7 = (node) => parseGemmAttributes(node, false);
|
||||
exports.parseGemmAttributesV7 = parseGemmAttributesV7;
|
||||
const parseGemmAttributesV11 = (node) => parseGemmAttributes(node, true);
|
||||
exports.parseGemmAttributesV11 = parseGemmAttributesV11;
|
||||
const createGemmProgramInfoLoader = (inputs, attributes) => {
|
||||
const metadata = {
|
||||
name: 'Gemm',
|
||||
inputNames: inputs.length === 3 ? ['A', 'B', 'C'] : ['A', 'B'],
|
||||
inputTypes: inputs.length === 3 ? [types_1.TextureType.unpacked, types_1.TextureType.unpacked, types_1.TextureType.unpacked] :
|
||||
[types_1.TextureType.unpacked, types_1.TextureType.unpacked],
|
||||
key: attributes.cacheKey
|
||||
};
|
||||
return Object.assign(Object.assign({}, metadata), { get: () => createGemmProgramInfo(metadata, inputs, attributes) });
|
||||
};
|
||||
const createGemmProgramInfo = (metadata, inputs, attributes) => {
|
||||
const aShape = inputs[0].dims.slice();
|
||||
const bShape = inputs[1].dims.slice();
|
||||
const [M, N] = util_1.GemmUtil.getShapeOfGemmResult(aShape, attributes.transA, bShape, attributes.transB, inputs.length === 3 ? inputs[2].dims : undefined);
|
||||
const outputShape = [M, N];
|
||||
if (!outputShape) {
|
||||
throw new Error('Can\'t use gemm on the given tensors');
|
||||
}
|
||||
let sharedDim = aShape[aShape.length - 1];
|
||||
let line = '';
|
||||
if (attributes.transA) {
|
||||
sharedDim = aShape[0];
|
||||
}
|
||||
if (attributes.transA && attributes.transB) {
|
||||
line = 'value += _A_T(a) * _B_T(b);';
|
||||
}
|
||||
else if (attributes.transA && !attributes.transB) {
|
||||
line = 'value += _A_T(a) * _B(b);';
|
||||
}
|
||||
else if (!attributes.transA && attributes.transB) {
|
||||
line = 'value += _A(a) * _B_T(b);';
|
||||
}
|
||||
else if (!attributes.transA && !attributes.transB) {
|
||||
line = 'value += _A(a) * _B(b);';
|
||||
}
|
||||
const rank = outputShape.length;
|
||||
const declareC = inputs.length === 3 ? `int c[${inputs[2].dims.length}];` : '';
|
||||
const broadcastC = inputs.length === 3 ? 'bcastIndices_C(indices, c);' : '';
|
||||
const calculateC = inputs.length === 3 ? 'value += beta * _C(c);' : '';
|
||||
const shaderSource = `
|
||||
float process(int indices[${rank}]) {
|
||||
int a[${rank}];
|
||||
int b[${rank}];
|
||||
${declareC}
|
||||
|
||||
copyVec(indices, a);
|
||||
copyVec(indices, b);
|
||||
${broadcastC}
|
||||
|
||||
float value = 0.0;
|
||||
for (int k=0; k<${sharedDim}; ++k) {
|
||||
a[${rank - 1}] = k;
|
||||
b[${rank - 2}] = k;
|
||||
${line}
|
||||
}
|
||||
|
||||
value = value * alpha;
|
||||
${calculateC}
|
||||
return value;
|
||||
}`;
|
||||
return Object.assign(Object.assign({}, metadata), { output: { dims: outputShape, type: inputs[0].type, textureType: types_1.TextureType.unpacked }, variables: [
|
||||
{ name: 'alpha', type: 'float', data: attributes.alpha }, { name: 'beta', type: 'float', data: attributes.beta }
|
||||
], shaderSource });
|
||||
};
|
||||
const validateInputs = (inputs, attributes) => {
|
||||
if (!inputs) {
|
||||
throw new Error('Input is missing');
|
||||
}
|
||||
if (attributes.isOptionalC && (inputs.length < 2 || inputs.length > 3)) {
|
||||
throw new Error('Invaid input shape.');
|
||||
}
|
||||
if (!attributes.isOptionalC && inputs.length !== 3) {
|
||||
throw new Error('Gemm requires 3 inputs');
|
||||
}
|
||||
// 'C' can be of dimensionality 1 or 2 only
|
||||
if (inputs.length === 3 && inputs[2].dims.length !== 1 && inputs[2].dims.length !== 2) {
|
||||
throw new Error('Invalid input shape of C');
|
||||
}
|
||||
if ((inputs[0].type !== 'float32' && inputs[0].type !== 'float64') ||
|
||||
(inputs[1].type !== 'float32' && inputs[1].type !== 'float64') ||
|
||||
(inputs.length === 3 && inputs[2].type !== 'float32' && inputs[2].type !== 'float64')) {
|
||||
throw new Error('Invalid input type.');
|
||||
}
|
||||
if ((inputs[0].type !== inputs[1].type) || (inputs.length === 3 && inputs[0].type !== inputs[2].type)) {
|
||||
throw new Error('Input types are mismatched');
|
||||
}
|
||||
};
|
||||
//# sourceMappingURL=gemm.js.map
|
||||
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/gemm.js.map
generated
vendored
Normal file
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/gemm.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"gemm.js","sourceRoot":"","sources":["gemm.ts"],"names":[],"mappings":";AAAA,4DAA4D;AAC5D,kCAAkC;;;AAElC,gFAAqG;AAIrG,wCAAuC;AAEvC,oCAAsF;AAU/E,MAAM,IAAI,GACb,CAAC,gBAAuC,EAAE,MAAgB,EAAE,UAA0B,EAAY,EAAE;IAClG,cAAc,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;IACnC,MAAM,MAAM,GAAG,gBAAgB,CAAC,GAAG,CAAC,2BAA2B,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,CAAC,CAAC;IAC7F,OAAO,CAAC,MAAM,CAAC,CAAC;AAClB,CAAC,CAAC;AALO,QAAA,IAAI,QAKX;AAEN,MAAM,mBAAmB,GAAG,CAAC,IAAgB,EAAE,WAAoB,EAAkB,EAAE;IACrF,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;IACzD,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;IACzD,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IACrD,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACnD,OAAO,IAAA,sDAA2B,EAAC,EAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,EAAC,CAAC,CAAC;AACjF,CAAC,CAAC;AAEK,MAAM,qBAAqB,GAA2C,CAAC,IAAgB,EAAkB,EAAE,CAC9G,mBAAmB,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AADxB,QAAA,qBAAqB,yBACG;AAE9B,MAAM,sBAAsB,GAA2C,CAAC,IAAgB,EAAkB,EAAE,CAC/G,mBAAmB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AADvB,QAAA,sBAAsB,0BACC;AAEpC,MAAM,2BAA2B,GAAG,CAAC,MAAgB,EAAE,UAA0B,EAAqB,EAAE;IACtG,MAAM,QAAQ,GAAG;QACf,IAAI,EAAE,MAAM;QACZ,UAAU,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC;QAC9D,UAAU,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,mBAAW,CAAC,QAAQ,EAAE,mBAAW,CAAC,QAAQ,EAAE,mBAAW,CAAC,QAAQ,CAAC,CAAC,CAAC;YACpE,CAAC,mBAAW,CAAC,QAAQ,EAAE,mBAAW,CAAC,QAAQ,CAAC;QAC9E,GAAG,EAAE,UAAU,CAAC,QAAQ;KACzB,CAAC;IAEF,uCAAW,QAAQ,KAAE,GAAG,EAAE,GAAG,EAAE,CAAC,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAC,IAAE;AACvF,CAAC,CAAC;AAEF,MAAM,qBAAqB,GACvB,CAAC,QAAyB,EAAE,MAAgB,EAAE,UAA0B,EAAe,EAAE;IACvF,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;IACtC,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;IACtC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,eAAQ,CAAC,oBAAoB,CACxC,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAC5G,MAAM,WAAW,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC3B,IAAI,CAAC,WAAW,EAAE;QAChB,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;KACzD;IACD,IAAI,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IAC1C,IAAI,IAAI,GAAG,EAAE,CAAC;IACd,IAAI,UAAU,CAAC,MAAM,EAAE;QACrB,SAAS,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;KACvB;IACD,IAAI,UAAU,CAAC,MAAM,IAAI,UAAU,CAAC,MAAM,EAAE;QAC1C,IAAI,GAAG,6BAA6B,CAAC;KACtC;SAAM,IAAI,UAAU,CAAC,MAAM,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE;QAClD,IAAI,GAAG,2BAA2B,CAAC;KACpC;SAAM,IAAI,CAAC,UAAU,CAAC,MAAM,IAAI,UAAU,CAAC,MAAM,EAAE;QAClD,IAAI,GAAG,2BAA2B,CAAC;KACpC;SAAM,IAAI,CAAC,UAAU,CAAC,MAAM,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE;QACnD,IAAI,GAAG,yBAAyB,CAAC;KAClC;IACD,MAAM,IAAI,GAAG,WAAW,CAAC,MAAM,CAAC;IAChC,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/E,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,6BAA6B,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5E,MAAM,UAAU,GAAG,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,EAAE,CAAC;IACvE,MAAM,YAAY,GAAG;kCACO,IAAI;kBACpB,IAAI;kBACJ,IAAI;YACV,QAAQ;;;;YAIR,UAAU;;;4BAGM,SAAS;kBACnB,IAAI,GAAG,CAAC;kBACR,IAAI,GAAG,CAAC;gBACV,IAAI;;;;YAIR,UAAU;;QAEd,CAAC;IACH,uCACK,QAAQ,KACX,MAAM,EAAE,EAAC,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,WAAW,EAAE,mBAAW,CAAC,QAAQ,EAAC,EACpF,SAAS,EAAE;YACT,EAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,CAAC,KAAK,EAAC,EAAE,EAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,CAAC,IAAI,EAAC;SAC7G,EACD,YAAY,IACZ;AACJ,CAAC,CAAC;AAEN,MAAM,cAAc,GAAG,CAAC,MAAgB,EAAE,UAA0B,EAAQ,EAAE;IAC5E,IAAI,CAAC,MAAM,EAAE;QACX,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;KACrC;IACD,IAAI,UAAU,CAAC,WAAW,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE;QACtE,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;KACxC;IACD,IAAI,CAAC,UAAU,CAAC,WAAW,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE;QAClD,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;KAC3C;IAED,2CAA2C;IAC3C,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE;QACrF,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;KAC7C;IAED,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC;QAC9D,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC;QAC9D,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,EAAE;QACzF,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC;KACxC;IAED,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE;QACrG,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;KAC/C;AACH,CAAC,CAAC"}
|
||||
137
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/gemm.ts
generated
vendored
Normal file
137
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/gemm.ts
generated
vendored
Normal file
@@ -0,0 +1,137 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../../../attribute-with-cache-key';
|
||||
import {Graph} from '../../../graph';
|
||||
import {OperatorImplementation, OperatorInitialization} from '../../../operators';
|
||||
import {Tensor} from '../../../tensor';
|
||||
import {GemmUtil} from '../../../util';
|
||||
import {WebGLInferenceHandler} from '../inference-handler';
|
||||
import {ProgramInfo, ProgramInfoLoader, ProgramMetadata, TextureType} from '../types';
|
||||
|
||||
export interface GemmAttributes extends AttributeWithCacheKey {
|
||||
transA: boolean;
|
||||
transB: boolean;
|
||||
alpha: number;
|
||||
beta: number;
|
||||
isOptionalC: boolean; // in opset 11, C becomes optional
|
||||
}
|
||||
|
||||
export const gemm: OperatorImplementation<GemmAttributes> =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: GemmAttributes): Tensor[] => {
|
||||
validateInputs(inputs, attributes);
|
||||
const output = inferenceHandler.run(createGemmProgramInfoLoader(inputs, attributes), inputs);
|
||||
return [output];
|
||||
};
|
||||
|
||||
const parseGemmAttributes = (node: Graph.Node, isOptionalC: boolean): GemmAttributes => {
|
||||
const transA = node.attributes.getInt('transA', 0) !== 0;
|
||||
const transB = node.attributes.getInt('transB', 0) !== 0;
|
||||
const alpha = node.attributes.getFloat('alpha', 1.0);
|
||||
const beta = node.attributes.getFloat('beta', 1.0);
|
||||
return createAttributeWithCacheKey({transA, transB, alpha, beta, isOptionalC});
|
||||
};
|
||||
|
||||
export const parseGemmAttributesV7: OperatorInitialization<GemmAttributes> = (node: Graph.Node): GemmAttributes =>
|
||||
parseGemmAttributes(node, false);
|
||||
|
||||
export const parseGemmAttributesV11: OperatorInitialization<GemmAttributes> = (node: Graph.Node): GemmAttributes =>
|
||||
parseGemmAttributes(node, true);
|
||||
|
||||
const createGemmProgramInfoLoader = (inputs: Tensor[], attributes: GemmAttributes): ProgramInfoLoader => {
|
||||
const metadata = {
|
||||
name: 'Gemm',
|
||||
inputNames: inputs.length === 3 ? ['A', 'B', 'C'] : ['A', 'B'],
|
||||
inputTypes: inputs.length === 3 ? [TextureType.unpacked, TextureType.unpacked, TextureType.unpacked] :
|
||||
[TextureType.unpacked, TextureType.unpacked],
|
||||
key: attributes.cacheKey
|
||||
};
|
||||
|
||||
return {...metadata, get: () => createGemmProgramInfo(metadata, inputs, attributes)};
|
||||
};
|
||||
|
||||
const createGemmProgramInfo =
|
||||
(metadata: ProgramMetadata, inputs: Tensor[], attributes: GemmAttributes): ProgramInfo => {
|
||||
const aShape = inputs[0].dims.slice();
|
||||
const bShape = inputs[1].dims.slice();
|
||||
const [M, N] = GemmUtil.getShapeOfGemmResult(
|
||||
aShape, attributes.transA, bShape, attributes.transB, inputs.length === 3 ? inputs[2].dims : undefined);
|
||||
const outputShape = [M, N];
|
||||
if (!outputShape) {
|
||||
throw new Error('Can\'t use gemm on the given tensors');
|
||||
}
|
||||
let sharedDim = aShape[aShape.length - 1];
|
||||
let line = '';
|
||||
if (attributes.transA) {
|
||||
sharedDim = aShape[0];
|
||||
}
|
||||
if (attributes.transA && attributes.transB) {
|
||||
line = 'value += _A_T(a) * _B_T(b);';
|
||||
} else if (attributes.transA && !attributes.transB) {
|
||||
line = 'value += _A_T(a) * _B(b);';
|
||||
} else if (!attributes.transA && attributes.transB) {
|
||||
line = 'value += _A(a) * _B_T(b);';
|
||||
} else if (!attributes.transA && !attributes.transB) {
|
||||
line = 'value += _A(a) * _B(b);';
|
||||
}
|
||||
const rank = outputShape.length;
|
||||
const declareC = inputs.length === 3 ? `int c[${inputs[2].dims.length}];` : '';
|
||||
const broadcastC = inputs.length === 3 ? 'bcastIndices_C(indices, c);' : '';
|
||||
const calculateC = inputs.length === 3 ? 'value += beta * _C(c);' : '';
|
||||
const shaderSource = `
|
||||
float process(int indices[${rank}]) {
|
||||
int a[${rank}];
|
||||
int b[${rank}];
|
||||
${declareC}
|
||||
|
||||
copyVec(indices, a);
|
||||
copyVec(indices, b);
|
||||
${broadcastC}
|
||||
|
||||
float value = 0.0;
|
||||
for (int k=0; k<${sharedDim}; ++k) {
|
||||
a[${rank - 1}] = k;
|
||||
b[${rank - 2}] = k;
|
||||
${line}
|
||||
}
|
||||
|
||||
value = value * alpha;
|
||||
${calculateC}
|
||||
return value;
|
||||
}`;
|
||||
return {
|
||||
...metadata,
|
||||
output: {dims: outputShape, type: inputs[0].type, textureType: TextureType.unpacked},
|
||||
variables: [
|
||||
{name: 'alpha', type: 'float', data: attributes.alpha}, {name: 'beta', type: 'float', data: attributes.beta}
|
||||
],
|
||||
shaderSource
|
||||
};
|
||||
};
|
||||
|
||||
const validateInputs = (inputs: Tensor[], attributes: GemmAttributes): void => {
|
||||
if (!inputs) {
|
||||
throw new Error('Input is missing');
|
||||
}
|
||||
if (attributes.isOptionalC && (inputs.length < 2 || inputs.length > 3)) {
|
||||
throw new Error('Invaid input shape.');
|
||||
}
|
||||
if (!attributes.isOptionalC && inputs.length !== 3) {
|
||||
throw new Error('Gemm requires 3 inputs');
|
||||
}
|
||||
|
||||
// 'C' can be of dimensionality 1 or 2 only
|
||||
if (inputs.length === 3 && inputs[2].dims.length !== 1 && inputs[2].dims.length !== 2) {
|
||||
throw new Error('Invalid input shape of C');
|
||||
}
|
||||
|
||||
if ((inputs[0].type !== 'float32' && inputs[0].type !== 'float64') ||
|
||||
(inputs[1].type !== 'float32' && inputs[1].type !== 'float64') ||
|
||||
(inputs.length === 3 && inputs[2].type !== 'float32' && inputs[2].type !== 'float64')) {
|
||||
throw new Error('Invalid input type.');
|
||||
}
|
||||
|
||||
if ((inputs[0].type !== inputs[1].type) || (inputs.length === 3 && inputs[0].type !== inputs[2].type)) {
|
||||
throw new Error('Input types are mismatched');
|
||||
}
|
||||
};
|
||||
75
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/im2col-pack.js
generated
vendored
Normal file
75
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/im2col-pack.js
generated
vendored
Normal file
@@ -0,0 +1,75 @@
|
||||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createPackedIm2ColProgramInfoLoader = void 0;
|
||||
const glsl_source_1 = require("../glsl-source");
|
||||
const types_1 = require("../types");
|
||||
const packing_utils_1 = require("./packing-utils");
|
||||
const createPackedIm2ColProgramMetadata = (cacheHint) => ({
|
||||
name: 'Im2Col (packed)',
|
||||
inputNames: ['A'],
|
||||
inputTypes: [types_1.TextureType.packed],
|
||||
cacheHint,
|
||||
});
|
||||
const createPackedIm2ColProgramInfo = (inferenceHandler, metadata, x, w, outputShape, attributes) => {
|
||||
const xshape = x.dims;
|
||||
const wshape = w.dims;
|
||||
const rowDim = 2;
|
||||
const colDim = 3;
|
||||
const rank = outputShape.length;
|
||||
const im2colShape = [wshape[1] * wshape[2] * wshape[3], outputShape[2] * outputShape[3]];
|
||||
const kernelSize = wshape[2] * wshape[3];
|
||||
const unpackChannel = (0, packing_utils_1.unpackFromChannel)();
|
||||
const glsl = (0, glsl_source_1.getGlsl)(inferenceHandler.session.backend.glContext.version);
|
||||
let unrolled = '';
|
||||
for (let row = 0; row <= 1; row++) {
|
||||
for (let col = 0; col <= 1; col++) {
|
||||
unrolled += `
|
||||
blockIndex = rc.x + ${col};
|
||||
pos = rc.y + ${row};
|
||||
|
||||
if(blockIndex < ${im2colShape[1]} && pos < ${im2colShape[0]}) {
|
||||
offsetY = int(blockIndex / (${outputShape[rank - 1]})) * ${attributes.strides[0]} -
|
||||
${attributes.pads[0]};
|
||||
d0 = offsetY + ${attributes.dilations[0]} * (imod(pos, ${kernelSize}) / ${wshape[2]});
|
||||
|
||||
if(d0 < ${xshape[rowDim]} && d0 >= 0) {
|
||||
offsetX = imod(blockIndex, ${outputShape[rank - 1]}) * ${attributes.strides[1]} -
|
||||
${attributes.pads[1]};
|
||||
d1 = offsetX + ${attributes.dilations[1]} * imod(imod(pos, ${kernelSize}), ${wshape[2]});
|
||||
|
||||
if(d1 < ${xshape[colDim]} && d1 >= 0) {
|
||||
|
||||
ch = int(float(pos)/ ${kernelSize}.);
|
||||
innerDims = vec2(d0, d1);
|
||||
result[${row * 2 + col}] = getChannel(
|
||||
getA(0, ch, int(innerDims.x),
|
||||
int(innerDims.y)), innerDims);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
`;
|
||||
}
|
||||
}
|
||||
const shaderSource = `
|
||||
${unpackChannel}
|
||||
|
||||
void main() {
|
||||
ivec2 rc = getOutputCoords();
|
||||
vec4 result = vec4(0.0);
|
||||
int blockIndex, pos, offsetY, d0, offsetX, d1, ch;
|
||||
vec2 innerDims;
|
||||
${unrolled}
|
||||
${glsl.output} = result;
|
||||
}
|
||||
`;
|
||||
return Object.assign(Object.assign({}, metadata), { output: { dims: im2colShape, type: x.type, textureType: types_1.TextureType.packed }, shaderSource, hasMain: true });
|
||||
};
|
||||
const createPackedIm2ColProgramInfoLoader = (inferenceHandler, x, w, outputShape, attributes) => {
|
||||
const metadata = createPackedIm2ColProgramMetadata(attributes.cacheKey);
|
||||
return Object.assign(Object.assign({}, metadata), { get: () => createPackedIm2ColProgramInfo(inferenceHandler, metadata, x, w, outputShape, attributes) });
|
||||
};
|
||||
exports.createPackedIm2ColProgramInfoLoader = createPackedIm2ColProgramInfoLoader;
|
||||
//# sourceMappingURL=im2col-pack.js.map
|
||||
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/im2col-pack.js.map
generated
vendored
Normal file
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/im2col-pack.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"im2col-pack.js","sourceRoot":"","sources":["im2col-pack.ts"],"names":[],"mappings":"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"}
|
||||
92
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/im2col-pack.ts
generated
vendored
Normal file
92
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/im2col-pack.ts
generated
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import {Tensor} from '../../../tensor';
|
||||
import {getGlsl} from '../glsl-source';
|
||||
import {WebGLInferenceHandler} from '../inference-handler';
|
||||
import {ProgramInfo, ProgramInfoLoader, ProgramMetadata, TextureType} from '../types';
|
||||
|
||||
import {ConvAttributes} from './conv';
|
||||
import {unpackFromChannel} from './packing-utils';
|
||||
|
||||
const createPackedIm2ColProgramMetadata = (cacheHint: string) => ({
|
||||
name: 'Im2Col (packed)',
|
||||
inputNames: ['A'],
|
||||
inputTypes: [TextureType.packed],
|
||||
cacheHint,
|
||||
});
|
||||
|
||||
const createPackedIm2ColProgramInfo =
|
||||
(inferenceHandler: WebGLInferenceHandler, metadata: ProgramMetadata, x: Tensor, w: Tensor,
|
||||
outputShape: readonly number[], attributes: ConvAttributes): ProgramInfo => {
|
||||
const xshape = x.dims;
|
||||
const wshape = w.dims;
|
||||
const rowDim = 2;
|
||||
const colDim = 3;
|
||||
const rank = outputShape.length;
|
||||
const im2colShape = [wshape[1] * wshape[2] * wshape[3], outputShape[2] * outputShape[3]];
|
||||
const kernelSize = wshape[2] * wshape[3];
|
||||
const unpackChannel = unpackFromChannel();
|
||||
const glsl = getGlsl(inferenceHandler.session.backend.glContext.version);
|
||||
let unrolled = '';
|
||||
|
||||
for (let row = 0; row <= 1; row++) {
|
||||
for (let col = 0; col <= 1; col++) {
|
||||
unrolled += `
|
||||
blockIndex = rc.x + ${col};
|
||||
pos = rc.y + ${row};
|
||||
|
||||
if(blockIndex < ${im2colShape[1]} && pos < ${im2colShape[0]}) {
|
||||
offsetY = int(blockIndex / (${outputShape[rank - 1]})) * ${attributes.strides[0]} -
|
||||
${attributes.pads[0]};
|
||||
d0 = offsetY + ${attributes.dilations[0]} * (imod(pos, ${kernelSize}) / ${wshape[2]});
|
||||
|
||||
if(d0 < ${xshape[rowDim]} && d0 >= 0) {
|
||||
offsetX = imod(blockIndex, ${outputShape[rank - 1]}) * ${attributes.strides[1]} -
|
||||
${attributes.pads[1]};
|
||||
d1 = offsetX + ${attributes.dilations[1]} * imod(imod(pos, ${kernelSize}), ${wshape[2]});
|
||||
|
||||
if(d1 < ${xshape[colDim]} && d1 >= 0) {
|
||||
|
||||
ch = int(float(pos)/ ${kernelSize}.);
|
||||
innerDims = vec2(d0, d1);
|
||||
result[${row * 2 + col}] = getChannel(
|
||||
getA(0, ch, int(innerDims.x),
|
||||
int(innerDims.y)), innerDims);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
`;
|
||||
}
|
||||
}
|
||||
|
||||
const shaderSource = `
|
||||
${unpackChannel}
|
||||
|
||||
void main() {
|
||||
ivec2 rc = getOutputCoords();
|
||||
vec4 result = vec4(0.0);
|
||||
int blockIndex, pos, offsetY, d0, offsetX, d1, ch;
|
||||
vec2 innerDims;
|
||||
${unrolled}
|
||||
${glsl.output} = result;
|
||||
}
|
||||
`;
|
||||
return {
|
||||
...metadata,
|
||||
output: {dims: im2colShape, type: x.type, textureType: TextureType.packed},
|
||||
shaderSource,
|
||||
hasMain: true
|
||||
};
|
||||
};
|
||||
|
||||
export const createPackedIm2ColProgramInfoLoader =
|
||||
(inferenceHandler: WebGLInferenceHandler, x: Tensor, w: Tensor, outputShape: readonly number[],
|
||||
attributes: ConvAttributes): ProgramInfoLoader => {
|
||||
const metadata = createPackedIm2ColProgramMetadata(attributes.cacheKey);
|
||||
return {
|
||||
...metadata,
|
||||
get: () => createPackedIm2ColProgramInfo(inferenceHandler, metadata, x, w, outputShape, attributes)
|
||||
};
|
||||
};
|
||||
73
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/im2col.js
generated
vendored
Normal file
73
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/im2col.js
generated
vendored
Normal file
@@ -0,0 +1,73 @@
|
||||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.calculateIm2ColDims = exports.createIm2ColProgramInfoLoader = void 0;
|
||||
const types_1 = require("../types");
|
||||
const createIm2ColProgramMetadata = (cacheHint) => ({
|
||||
name: 'Im2Col',
|
||||
inputNames: ['X'],
|
||||
inputTypes: [types_1.TextureType.unpacked],
|
||||
cacheHint,
|
||||
});
|
||||
const createIm2ColProgramInfo = (inferenceHandler, metadata, x, w, outputShape, attributes) => {
|
||||
const xshape = x.dims;
|
||||
const wshape = w.dims;
|
||||
const rank = outputShape.length;
|
||||
const im2colDims = (0, exports.calculateIm2ColDims)(xshape, wshape, outputShape, 4);
|
||||
const shaderSource = `
|
||||
const int XC = ${xshape[1]};
|
||||
const int XH = ${xshape[2]};
|
||||
const int XW = ${xshape[3]};
|
||||
const int KH = ${attributes.kernelShape[0]};
|
||||
const int KW = ${attributes.kernelShape[1]};
|
||||
const int dilationH = ${attributes.dilations[0]};
|
||||
const int dilationW = ${attributes.dilations[1]};
|
||||
const int strideH = ${attributes.strides[0]};
|
||||
const int strideW = ${attributes.strides[1]};
|
||||
const int padH = ${attributes.pads[0]};
|
||||
const int padW = ${attributes.pads[1]};
|
||||
const int KHKW = KH*KW;
|
||||
const int XCKHKW = XC * KHKW;
|
||||
const int outputChannels = 4;
|
||||
vec4 process(int indices[${rank}]) {
|
||||
int b = indices[0]; // batch size
|
||||
int oh = indices[1] * strideH - padH; //output height
|
||||
int ow = indices[2] * strideW - padW; //output width
|
||||
int p = indices[3] * outputChannels; //patch
|
||||
vec4 value = vec4(0.0);
|
||||
for(int i=0; i < outputChannels; ++i) {
|
||||
if(p < XCKHKW) {
|
||||
int patchC = p / KHKW;
|
||||
int patchH = (p - patchC*KHKW) / KW;
|
||||
int patchW = (p - patchC*KHKW) - patchH * KW;
|
||||
int xh2 = oh + patchH * dilationH;
|
||||
int xw2 = ow + patchW * dilationW;
|
||||
int x[${xshape.length}];
|
||||
x[0] = b;
|
||||
x[1] = patchC;
|
||||
x[2] = xh2;
|
||||
x[3] = xw2;
|
||||
if(xh2 >= 0 &&
|
||||
xh2 < XH &&
|
||||
xw2 >= 0 &&
|
||||
xw2 < XW) {
|
||||
value[i] = _X(x);
|
||||
}
|
||||
}
|
||||
++p;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
`;
|
||||
return Object.assign(Object.assign({}, metadata), { output: { dims: im2colDims, type: x.type, textureType: types_1.TextureType.packedLastDimension }, shaderSource });
|
||||
};
|
||||
const createIm2ColProgramInfoLoader = (inferenceHandler, x, w, outputShape, attributes) => {
|
||||
const metadata = createIm2ColProgramMetadata(attributes.cacheKey);
|
||||
return Object.assign(Object.assign({}, metadata), { get: () => createIm2ColProgramInfo(inferenceHandler, metadata, x, w, outputShape, attributes) });
|
||||
};
|
||||
exports.createIm2ColProgramInfoLoader = createIm2ColProgramInfoLoader;
|
||||
const calculateIm2ColDims = (inputShape, kernelShape, outputShape, channels = 4) => [outputShape[0], outputShape[2], outputShape[3],
|
||||
Math.ceil(inputShape[1] * kernelShape[2] * kernelShape[3] / channels)];
|
||||
exports.calculateIm2ColDims = calculateIm2ColDims;
|
||||
//# sourceMappingURL=im2col.js.map
|
||||
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/im2col.js.map
generated
vendored
Normal file
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/im2col.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"im2col.js","sourceRoot":"","sources":["im2col.ts"],"names":[],"mappings":";AAAA,4DAA4D;AAC5D,kCAAkC;;;AAIlC,oCAAsF;AAItF,MAAM,2BAA2B,GAAG,CAAC,SAAiB,EAAE,EAAE,CAAC,CAAC;IAC1D,IAAI,EAAE,QAAQ;IACd,UAAU,EAAE,CAAC,GAAG,CAAC;IACjB,UAAU,EAAE,CAAC,mBAAW,CAAC,QAAQ,CAAC;IAClC,SAAS;CACV,CAAC,CAAC;AAEH,MAAM,uBAAuB,GACzB,CAAC,gBAAuC,EAAE,QAAyB,EAAE,CAAS,EAAE,CAAS,EACxF,WAA8B,EAAE,UAA0B,EAAe,EAAE;IAC1E,MAAM,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC;IACtB,MAAM,MAAM,GAAG,CAAC,CAAC,IAAI,CAAC;IAEtB,MAAM,IAAI,GAAG,WAAW,CAAC,MAAM,CAAC;IAChC,MAAM,UAAU,GAAG,IAAA,2BAAmB,EAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC,CAAC,CAAC;IAEvE,MAAM,YAAY,GAAG;yBACF,MAAM,CAAC,CAAC,CAAC;yBACT,MAAM,CAAC,CAAC,CAAC;yBACT,MAAM,CAAC,CAAC,CAAC;yBACT,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC;yBACzB,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC;gCAClB,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC;gCACvB,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC;8BACzB,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC;8BACrB,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC;2BACxB,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;2BAClB,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;;;;mCAIV,IAAI;;;;;;;;;;;;;sBAajB,MAAM,CAAC,MAAM;;;;;;;;;;;;;;;;SAgB1B,CAAC;IACJ,uCACK,QAAQ,KACX,MAAM,EAAE,EAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,WAAW,EAAE,mBAAW,CAAC,mBAAmB,EAAC,EACtF,YAAY,IACZ;AACJ,CAAC,CAAC;AAEC,MAAM,6BAA6B,GACtC,CAAC,gBAAuC,EAAE,CAAS,EAAE,CAAS,EAAE,WAA8B,EAC7F,UAA0B,EAAqB,EAAE;IAChD,MAAM,QAAQ,GAAG,2BAA2B,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;IAClE,uCACK,QAAQ,KACX,GAAG,EAAE,GAAG,EAAE,CAAC,uBAAuB,CAAC,gBAAgB,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC,EAAE,WAAW,EAAE,UAAU,CAAC,IAC7F;AACJ,CAAC,CAAC;AARO,QAAA,6BAA6B,iCAQpC;AAGC,MAAM,mBAAmB,GAC5B,CAAC,UAA6B,EAAE,WAA8B,EAAE,WAA8B,EAAE,QAAQ,GAAG,CAAC,EAC/F,EAAE,CACP,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC;IAC9C,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC;AAJvE,QAAA,mBAAmB,uBAIoD"}
|
||||
93
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/im2col.ts
generated
vendored
Normal file
93
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/im2col.ts
generated
vendored
Normal file
@@ -0,0 +1,93 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import {Tensor} from '../../../tensor';
|
||||
import {WebGLInferenceHandler} from '../inference-handler';
|
||||
import {ProgramInfo, ProgramInfoLoader, ProgramMetadata, TextureType} from '../types';
|
||||
|
||||
import {ConvAttributes} from './conv';
|
||||
|
||||
const createIm2ColProgramMetadata = (cacheHint: string) => ({
|
||||
name: 'Im2Col',
|
||||
inputNames: ['X'],
|
||||
inputTypes: [TextureType.unpacked],
|
||||
cacheHint,
|
||||
});
|
||||
|
||||
const createIm2ColProgramInfo =
|
||||
(inferenceHandler: WebGLInferenceHandler, metadata: ProgramMetadata, x: Tensor, w: Tensor,
|
||||
outputShape: readonly number[], attributes: ConvAttributes): ProgramInfo => {
|
||||
const xshape = x.dims;
|
||||
const wshape = w.dims;
|
||||
|
||||
const rank = outputShape.length;
|
||||
const im2colDims = calculateIm2ColDims(xshape, wshape, outputShape, 4);
|
||||
|
||||
const shaderSource = `
|
||||
const int XC = ${xshape[1]};
|
||||
const int XH = ${xshape[2]};
|
||||
const int XW = ${xshape[3]};
|
||||
const int KH = ${attributes.kernelShape[0]};
|
||||
const int KW = ${attributes.kernelShape[1]};
|
||||
const int dilationH = ${attributes.dilations[0]};
|
||||
const int dilationW = ${attributes.dilations[1]};
|
||||
const int strideH = ${attributes.strides[0]};
|
||||
const int strideW = ${attributes.strides[1]};
|
||||
const int padH = ${attributes.pads[0]};
|
||||
const int padW = ${attributes.pads[1]};
|
||||
const int KHKW = KH*KW;
|
||||
const int XCKHKW = XC * KHKW;
|
||||
const int outputChannels = 4;
|
||||
vec4 process(int indices[${rank}]) {
|
||||
int b = indices[0]; // batch size
|
||||
int oh = indices[1] * strideH - padH; //output height
|
||||
int ow = indices[2] * strideW - padW; //output width
|
||||
int p = indices[3] * outputChannels; //patch
|
||||
vec4 value = vec4(0.0);
|
||||
for(int i=0; i < outputChannels; ++i) {
|
||||
if(p < XCKHKW) {
|
||||
int patchC = p / KHKW;
|
||||
int patchH = (p - patchC*KHKW) / KW;
|
||||
int patchW = (p - patchC*KHKW) - patchH * KW;
|
||||
int xh2 = oh + patchH * dilationH;
|
||||
int xw2 = ow + patchW * dilationW;
|
||||
int x[${xshape.length}];
|
||||
x[0] = b;
|
||||
x[1] = patchC;
|
||||
x[2] = xh2;
|
||||
x[3] = xw2;
|
||||
if(xh2 >= 0 &&
|
||||
xh2 < XH &&
|
||||
xw2 >= 0 &&
|
||||
xw2 < XW) {
|
||||
value[i] = _X(x);
|
||||
}
|
||||
}
|
||||
++p;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
`;
|
||||
return {
|
||||
...metadata,
|
||||
output: {dims: im2colDims, type: x.type, textureType: TextureType.packedLastDimension},
|
||||
shaderSource
|
||||
};
|
||||
};
|
||||
|
||||
export const createIm2ColProgramInfoLoader =
|
||||
(inferenceHandler: WebGLInferenceHandler, x: Tensor, w: Tensor, outputShape: readonly number[],
|
||||
attributes: ConvAttributes): ProgramInfoLoader => {
|
||||
const metadata = createIm2ColProgramMetadata(attributes.cacheKey);
|
||||
return {
|
||||
...metadata,
|
||||
get: () => createIm2ColProgramInfo(inferenceHandler, metadata, x, w, outputShape, attributes)
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
export const calculateIm2ColDims =
|
||||
(inputShape: readonly number[], kernelShape: readonly number[], outputShape: readonly number[], channels = 4):
|
||||
number[] =>
|
||||
[outputShape[0], outputShape[2], outputShape[3],
|
||||
Math.ceil(inputShape[1] * kernelShape[2] * kernelShape[3] / channels)];
|
||||
74
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/image-scaler.js
generated
vendored
Normal file
74
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/image-scaler.js
generated
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.parseImageScalerAttributes = exports.imageScaler = void 0;
|
||||
const attribute_with_cache_key_1 = require("../../../attribute-with-cache-key");
|
||||
const types_1 = require("../types");
|
||||
const imageScaler = (inferenceHandler, inputs, attributes) => {
|
||||
validateInputs(inputs);
|
||||
const output = inferenceHandler.run(createImageScalerProgramInfoLoader(inferenceHandler, inputs, attributes), inputs);
|
||||
return [output];
|
||||
};
|
||||
exports.imageScaler = imageScaler;
|
||||
const parseImageScalerAttributes = (node) => {
|
||||
const scale = node.attributes.getFloat('scale');
|
||||
const bias = node.attributes.getFloats('bias');
|
||||
return (0, attribute_with_cache_key_1.createAttributeWithCacheKey)({ scale, bias });
|
||||
};
|
||||
exports.parseImageScalerAttributes = parseImageScalerAttributes;
|
||||
const imageScalerProgramMetadata = {
|
||||
name: 'ImageScaler',
|
||||
inputNames: ['X'],
|
||||
inputTypes: [types_1.TextureType.unpacked],
|
||||
};
|
||||
const createImageScalerProgramInfo = (handler, metadata, inputs, attributes) => {
|
||||
const outputShape = inputs[0].dims.slice();
|
||||
const rank = outputShape.length;
|
||||
const getBiasMethod = createGetBiasMethod(attributes.bias.length);
|
||||
const shaderSource = `
|
||||
${getBiasMethod}
|
||||
float process(int indices[${rank}]) {
|
||||
return _X(indices) * scale + getBias(bias, indices[1]);
|
||||
}`;
|
||||
return Object.assign(Object.assign({}, metadata), { output: { dims: outputShape, type: inputs[0].type, textureType: types_1.TextureType.unpacked }, variables: [
|
||||
{ name: 'bias', type: 'float', arrayLength: attributes.bias.length, data: attributes.bias },
|
||||
{ name: 'scale', type: 'float', data: attributes.scale }
|
||||
], shaderSource });
|
||||
};
|
||||
const createImageScalerProgramInfoLoader = (handler, inputs, attributes) => {
|
||||
const metadata = Object.assign(Object.assign({}, imageScalerProgramMetadata), { cacheHint: attributes.cacheKey });
|
||||
return Object.assign(Object.assign({}, metadata), { get: () => createImageScalerProgramInfo(handler, metadata, inputs, attributes) });
|
||||
};
|
||||
const createGetBiasMethod = (numChannels) => {
|
||||
const codeLines = [`float getBias(float bias[${numChannels}], int channel) {`];
|
||||
for (let i = 0; i < numChannels; ++i) {
|
||||
if (i === 0) {
|
||||
codeLines.push('\t' +
|
||||
`if (channel == ${i}) { return bias[${i}]; }`);
|
||||
}
|
||||
else if (i === numChannels - 1) {
|
||||
codeLines.push('\t' +
|
||||
`else { return bias[${i}]; }`);
|
||||
}
|
||||
else {
|
||||
codeLines.push('\t' +
|
||||
`else if (channel == ${i}) { return bias[${i}]; }`);
|
||||
}
|
||||
}
|
||||
codeLines.push('\t' +
|
||||
'}');
|
||||
return codeLines.join('\n');
|
||||
};
|
||||
const validateInputs = (inputs) => {
|
||||
if (!inputs || inputs.length !== 1) {
|
||||
throw new Error('ImageScaler requires 1 input.');
|
||||
}
|
||||
if (inputs[0].dims.length !== 4) {
|
||||
throw new Error('Invalid input shape.');
|
||||
}
|
||||
if (inputs[0].type !== 'float32' && inputs[0].type !== 'float64') {
|
||||
throw new Error('Invalid input type.');
|
||||
}
|
||||
};
|
||||
//# sourceMappingURL=image-scaler.js.map
|
||||
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/image-scaler.js.map
generated
vendored
Normal file
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/image-scaler.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"image-scaler.js","sourceRoot":"","sources":["image-scaler.ts"],"names":[],"mappings":"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"}
|
||||
98
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/image-scaler.ts
generated
vendored
Normal file
98
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/image-scaler.ts
generated
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../../../attribute-with-cache-key';
|
||||
import {Graph} from '../../../graph';
|
||||
import {OperatorImplementation, OperatorInitialization} from '../../../operators';
|
||||
import {Tensor} from '../../../tensor';
|
||||
import {WebGLInferenceHandler} from '../inference-handler';
|
||||
import {ProgramInfo, ProgramInfoLoader, ProgramMetadata, TextureType} from '../types';
|
||||
|
||||
export interface ImageScalerAttributes extends AttributeWithCacheKey {
|
||||
scale: number;
|
||||
bias: number[];
|
||||
}
|
||||
|
||||
export const imageScaler: OperatorImplementation<ImageScalerAttributes> =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: ImageScalerAttributes): Tensor[] => {
|
||||
validateInputs(inputs);
|
||||
const output =
|
||||
inferenceHandler.run(createImageScalerProgramInfoLoader(inferenceHandler, inputs, attributes), inputs);
|
||||
return [output];
|
||||
};
|
||||
|
||||
export const parseImageScalerAttributes: OperatorInitialization<ImageScalerAttributes> =
|
||||
(node: Graph.Node): ImageScalerAttributes => {
|
||||
const scale = node.attributes.getFloat('scale');
|
||||
const bias = node.attributes.getFloats('bias');
|
||||
return createAttributeWithCacheKey({scale, bias});
|
||||
};
|
||||
|
||||
const imageScalerProgramMetadata = {
|
||||
name: 'ImageScaler',
|
||||
inputNames: ['X'],
|
||||
inputTypes: [TextureType.unpacked],
|
||||
};
|
||||
|
||||
const createImageScalerProgramInfo =
|
||||
(handler: WebGLInferenceHandler, metadata: ProgramMetadata, inputs: Tensor[], attributes: ImageScalerAttributes):
|
||||
ProgramInfo => {
|
||||
const outputShape = inputs[0].dims.slice();
|
||||
const rank = outputShape.length;
|
||||
const getBiasMethod = createGetBiasMethod(attributes.bias.length);
|
||||
const shaderSource = `
|
||||
${getBiasMethod}
|
||||
float process(int indices[${rank}]) {
|
||||
return _X(indices) * scale + getBias(bias, indices[1]);
|
||||
}`;
|
||||
return {
|
||||
...metadata,
|
||||
output: {dims: outputShape, type: inputs[0].type, textureType: TextureType.unpacked},
|
||||
variables: [
|
||||
{name: 'bias', type: 'float', arrayLength: attributes.bias.length, data: attributes.bias},
|
||||
{name: 'scale', type: 'float', data: attributes.scale}
|
||||
],
|
||||
shaderSource
|
||||
};
|
||||
};
|
||||
|
||||
const createImageScalerProgramInfoLoader =
|
||||
(handler: WebGLInferenceHandler, inputs: Tensor[], attributes: ImageScalerAttributes): ProgramInfoLoader => {
|
||||
const metadata = {...imageScalerProgramMetadata, cacheHint: attributes.cacheKey};
|
||||
return {...metadata, get: () => createImageScalerProgramInfo(handler, metadata, inputs, attributes)};
|
||||
};
|
||||
|
||||
const createGetBiasMethod = (numChannels: number): string => {
|
||||
const codeLines: string[] = [`float getBias(float bias[${numChannels}], int channel) {`];
|
||||
for (let i = 0; i < numChannels; ++i) {
|
||||
if (i === 0) {
|
||||
codeLines.push(
|
||||
'\t' +
|
||||
`if (channel == ${i}) { return bias[${i}]; }`);
|
||||
} else if (i === numChannels - 1) {
|
||||
codeLines.push(
|
||||
'\t' +
|
||||
`else { return bias[${i}]; }`);
|
||||
} else {
|
||||
codeLines.push(
|
||||
'\t' +
|
||||
`else if (channel == ${i}) { return bias[${i}]; }`);
|
||||
}
|
||||
}
|
||||
codeLines.push(
|
||||
'\t' +
|
||||
'}');
|
||||
return codeLines.join('\n');
|
||||
};
|
||||
|
||||
const validateInputs = (inputs: Tensor[]): void => {
|
||||
if (!inputs || inputs.length !== 1) {
|
||||
throw new Error('ImageScaler requires 1 input.');
|
||||
}
|
||||
if (inputs[0].dims.length !== 4) {
|
||||
throw new Error('Invalid input shape.');
|
||||
}
|
||||
if (inputs[0].type !== 'float32' && inputs[0].type !== 'float64') {
|
||||
throw new Error('Invalid input type.');
|
||||
}
|
||||
};
|
||||
120
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/instance-normalization.js
generated
vendored
Normal file
120
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/instance-normalization.js
generated
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.parseInstanceNormalizationAttributes = exports.instanceNormalization = void 0;
|
||||
const glsl_source_1 = require("../glsl-source");
|
||||
const types_1 = require("../types");
|
||||
const instanceNormalization = (inferenceHandler, inputs, epsilon) => {
|
||||
validateInputs(inputs);
|
||||
const meanAndVariance = inferenceHandler.run(createMeanAndVarianceProgramInfoLoader(inputs[0]), inputs);
|
||||
const output = inferenceHandler.run(createComputeOutputProgramInfoLoader(inferenceHandler, inputs[0], epsilon, meanAndVariance.dims), [inputs[0], meanAndVariance, inputs[1], inputs[2]]);
|
||||
return [output];
|
||||
};
|
||||
exports.instanceNormalization = instanceNormalization;
|
||||
const parseInstanceNormalizationAttributes = (node) => node.attributes.getFloat('epsilon', 1e-5);
|
||||
exports.parseInstanceNormalizationAttributes = parseInstanceNormalizationAttributes;
|
||||
const meanAndVarianceProgramMetadata = {
|
||||
name: 'InstanceNormalization_MeanAndVariance',
|
||||
inputNames: ['X'],
|
||||
inputTypes: [types_1.TextureType.unpacked],
|
||||
};
|
||||
const createMeanAndVarianceProgramInfo = (metadata, input) => {
|
||||
const xDims = input.dims.slice();
|
||||
const channel = xDims[1];
|
||||
const channelSize = xDims[2] * xDims[3];
|
||||
const outputShape = [xDims[0], channel];
|
||||
const shaderSource = `
|
||||
vec4 process(int[2] indices) {
|
||||
vec4 v = vec4(0.0);
|
||||
int a[4];
|
||||
a[0] = indices[0];
|
||||
a[1] = indices[1];
|
||||
float temp = 0.0;
|
||||
for(int a2=0; a2<${xDims[2]}; a2++) {
|
||||
a[2] = a2;
|
||||
for(int a3=0; a3<${xDims[3]}; a3++) {
|
||||
a[3] = a3;
|
||||
float x = _X(a);
|
||||
temp += x;
|
||||
}
|
||||
}
|
||||
float mean = temp / float(${channelSize});
|
||||
temp = 0.0;
|
||||
for(int a2=0; a2<${xDims[2]}; a2++) {
|
||||
a[2] = a2;
|
||||
for(int a3=0; a3<${xDims[3]}; a3++) {
|
||||
a[3] = a3;
|
||||
float x = _X(a);
|
||||
temp += (x - mean) * (x - mean);
|
||||
}
|
||||
}
|
||||
v.r = mean;
|
||||
v.g = temp / float(${channelSize});
|
||||
|
||||
return v;
|
||||
}`;
|
||||
return Object.assign(Object.assign({}, metadata), { output: { dims: outputShape, type: input.type, textureType: types_1.TextureType.packedLastDimension }, shaderSource });
|
||||
};
|
||||
const createMeanAndVarianceProgramInfoLoader = (input) => (Object.assign(Object.assign({}, meanAndVarianceProgramMetadata), { get: () => createMeanAndVarianceProgramInfo(meanAndVarianceProgramMetadata, input) }));
|
||||
const computeOutputProgramMetadata = {
|
||||
name: 'InstanceNormalization_ComputeOutput',
|
||||
inputNames: ['X', 'MeanAndVariance', 'Scale', 'B'],
|
||||
inputTypes: [types_1.TextureType.unpacked, types_1.TextureType.packedLastDimension, types_1.TextureType.unpacked, types_1.TextureType.unpacked],
|
||||
};
|
||||
const createComputeOutputProgramInfo = (inferenceHandler, metadata, input, epsilon, meanAndVarianceShape) => {
|
||||
const glsl = (0, glsl_source_1.getGlsl)(inferenceHandler.session.backend.glContext.version);
|
||||
const [textureWidth, textureHeight] = inferenceHandler.calculateTextureWidthAndHeight(meanAndVarianceShape, types_1.TextureType.packedLastDimension);
|
||||
const [meanAndVarianceWidth, meanAndVarianceHeight] = [textureWidth / 4, textureHeight];
|
||||
const shaderSource = `
|
||||
vec4 get_MeanAndVariance(int[2] mv) {
|
||||
int offset = indicesToOffset_MeanAndVariance(mv);
|
||||
vec2 coords = offsetToCoords(offset, ${meanAndVarianceWidth}, ${meanAndVarianceHeight});
|
||||
return ${glsl.texture2D}(MeanAndVariance, coords);
|
||||
}
|
||||
|
||||
float process(int[4] indices) {
|
||||
int mv[2];
|
||||
mv[0] = indices[0];
|
||||
mv[1] = indices[1];
|
||||
vec4 mean_and_variance = get_MeanAndVariance(mv);
|
||||
float mean = mean_and_variance.r;
|
||||
float variance = mean_and_variance.g;
|
||||
|
||||
int sb[1];
|
||||
sb[0] = indices[1];
|
||||
float scale = _Scale(sb);
|
||||
float b = _B(sb);
|
||||
|
||||
return scale * (_X(indices) - mean) / sqrt(variance + epsilon) + b;
|
||||
}`;
|
||||
return Object.assign(Object.assign({}, metadata), { output: { dims: input.dims, type: input.type, textureType: types_1.TextureType.unpacked }, variables: [{ name: 'epsilon', type: 'float', data: epsilon }], shaderSource });
|
||||
};
|
||||
const createComputeOutputProgramInfoLoader = (inferenceHandler, input, epsilon, meanAndVarianceShape) => {
|
||||
const metadata = Object.assign(Object.assign({}, computeOutputProgramMetadata), { cacheHint: `${epsilon}` });
|
||||
return Object.assign(Object.assign({}, metadata), { get: () => createComputeOutputProgramInfo(inferenceHandler, metadata, input, epsilon, meanAndVarianceShape) });
|
||||
};
|
||||
const validateInputs = (inputs) => {
|
||||
if (!inputs || inputs.length !== 3) {
|
||||
throw new Error('InstanceNormalization requires 3 inputs.');
|
||||
}
|
||||
const X = inputs[0];
|
||||
const scale = inputs[1];
|
||||
const B = inputs[2];
|
||||
// input should at least have three dimensions - N,C,dim1,...,dimn
|
||||
// other inputs can have only one dimensions
|
||||
if (X.dims.length < 3 || scale.dims.length !== 1 || B.dims.length !== 1) {
|
||||
throw new Error('Invalid input shape.');
|
||||
}
|
||||
if (scale.dims[0] !== X.dims[1] || B.dims[0] !== X.dims[1]) {
|
||||
throw new Error('Input shapes are mismatched.');
|
||||
}
|
||||
if ((X.type !== 'float32' && X.type !== 'float64') || (scale.type !== 'float32' && scale.type !== 'float64') ||
|
||||
(B.type !== 'float32' && B.type !== 'float64')) {
|
||||
throw new Error('Invalid input type.');
|
||||
}
|
||||
if (inputs[0].dims.length !== 4) {
|
||||
throw new Error('Only support 4-D input shape.');
|
||||
}
|
||||
};
|
||||
//# sourceMappingURL=instance-normalization.js.map
|
||||
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/instance-normalization.js.map
generated
vendored
Normal file
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/instance-normalization.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"instance-normalization.js","sourceRoot":"","sources":["instance-normalization.ts"],"names":[],"mappings":"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"}
|
||||
156
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/instance-normalization.ts
generated
vendored
Normal file
156
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/instance-normalization.ts
generated
vendored
Normal file
@@ -0,0 +1,156 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import {Graph} from '../../../graph';
|
||||
import {OperatorImplementation, OperatorInitialization} from '../../../operators';
|
||||
import {Tensor} from '../../../tensor';
|
||||
import {getGlsl} from '../glsl-source';
|
||||
import {WebGLInferenceHandler} from '../inference-handler';
|
||||
import {ProgramInfo, ProgramInfoLoader, ProgramMetadata, TextureType} from '../types';
|
||||
|
||||
export const instanceNormalization: OperatorImplementation<number> =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], epsilon: number): Tensor[] => {
|
||||
validateInputs(inputs);
|
||||
|
||||
const meanAndVariance = inferenceHandler.run(createMeanAndVarianceProgramInfoLoader(inputs[0]), inputs);
|
||||
const output = inferenceHandler.run(
|
||||
createComputeOutputProgramInfoLoader(inferenceHandler, inputs[0], epsilon, meanAndVariance.dims),
|
||||
[inputs[0], meanAndVariance, inputs[1], inputs[2]]);
|
||||
return [output];
|
||||
};
|
||||
|
||||
export const parseInstanceNormalizationAttributes: OperatorInitialization<number> = (node: Graph.Node): number =>
|
||||
node.attributes.getFloat('epsilon', 1e-5);
|
||||
|
||||
const meanAndVarianceProgramMetadata = {
|
||||
name: 'InstanceNormalization_MeanAndVariance',
|
||||
inputNames: ['X'],
|
||||
inputTypes: [TextureType.unpacked],
|
||||
};
|
||||
|
||||
const createMeanAndVarianceProgramInfo = (metadata: ProgramMetadata, input: Tensor): ProgramInfo => {
|
||||
const xDims = input.dims.slice();
|
||||
const channel = xDims[1];
|
||||
const channelSize = xDims[2] * xDims[3];
|
||||
const outputShape = [xDims[0], channel];
|
||||
|
||||
const shaderSource = `
|
||||
vec4 process(int[2] indices) {
|
||||
vec4 v = vec4(0.0);
|
||||
int a[4];
|
||||
a[0] = indices[0];
|
||||
a[1] = indices[1];
|
||||
float temp = 0.0;
|
||||
for(int a2=0; a2<${xDims[2]}; a2++) {
|
||||
a[2] = a2;
|
||||
for(int a3=0; a3<${xDims[3]}; a3++) {
|
||||
a[3] = a3;
|
||||
float x = _X(a);
|
||||
temp += x;
|
||||
}
|
||||
}
|
||||
float mean = temp / float(${channelSize});
|
||||
temp = 0.0;
|
||||
for(int a2=0; a2<${xDims[2]}; a2++) {
|
||||
a[2] = a2;
|
||||
for(int a3=0; a3<${xDims[3]}; a3++) {
|
||||
a[3] = a3;
|
||||
float x = _X(a);
|
||||
temp += (x - mean) * (x - mean);
|
||||
}
|
||||
}
|
||||
v.r = mean;
|
||||
v.g = temp / float(${channelSize});
|
||||
|
||||
return v;
|
||||
}`;
|
||||
return {
|
||||
...metadata,
|
||||
output: {dims: outputShape, type: input.type, textureType: TextureType.packedLastDimension},
|
||||
shaderSource
|
||||
};
|
||||
};
|
||||
|
||||
const createMeanAndVarianceProgramInfoLoader = (input: Tensor): ProgramInfoLoader => ({
|
||||
...meanAndVarianceProgramMetadata,
|
||||
get: () => createMeanAndVarianceProgramInfo(meanAndVarianceProgramMetadata, input)
|
||||
});
|
||||
|
||||
const computeOutputProgramMetadata = {
|
||||
name: 'InstanceNormalization_ComputeOutput',
|
||||
inputNames: ['X', 'MeanAndVariance', 'Scale', 'B'],
|
||||
inputTypes: [TextureType.unpacked, TextureType.packedLastDimension, TextureType.unpacked, TextureType.unpacked],
|
||||
};
|
||||
|
||||
const createComputeOutputProgramInfo =
|
||||
(inferenceHandler: WebGLInferenceHandler, metadata: ProgramMetadata, input: Tensor, epsilon: number,
|
||||
meanAndVarianceShape: readonly number[]): ProgramInfo => {
|
||||
const glsl = getGlsl(inferenceHandler.session.backend.glContext.version);
|
||||
const [textureWidth, textureHeight] =
|
||||
inferenceHandler.calculateTextureWidthAndHeight(meanAndVarianceShape, TextureType.packedLastDimension);
|
||||
const [meanAndVarianceWidth, meanAndVarianceHeight] = [textureWidth / 4, textureHeight];
|
||||
const shaderSource = `
|
||||
vec4 get_MeanAndVariance(int[2] mv) {
|
||||
int offset = indicesToOffset_MeanAndVariance(mv);
|
||||
vec2 coords = offsetToCoords(offset, ${meanAndVarianceWidth}, ${meanAndVarianceHeight});
|
||||
return ${glsl.texture2D}(MeanAndVariance, coords);
|
||||
}
|
||||
|
||||
float process(int[4] indices) {
|
||||
int mv[2];
|
||||
mv[0] = indices[0];
|
||||
mv[1] = indices[1];
|
||||
vec4 mean_and_variance = get_MeanAndVariance(mv);
|
||||
float mean = mean_and_variance.r;
|
||||
float variance = mean_and_variance.g;
|
||||
|
||||
int sb[1];
|
||||
sb[0] = indices[1];
|
||||
float scale = _Scale(sb);
|
||||
float b = _B(sb);
|
||||
|
||||
return scale * (_X(indices) - mean) / sqrt(variance + epsilon) + b;
|
||||
}`;
|
||||
return {
|
||||
...metadata,
|
||||
output: {dims: input.dims, type: input.type, textureType: TextureType.unpacked},
|
||||
variables: [{name: 'epsilon', type: 'float', data: epsilon}],
|
||||
shaderSource
|
||||
};
|
||||
};
|
||||
|
||||
const createComputeOutputProgramInfoLoader =
|
||||
(inferenceHandler: WebGLInferenceHandler, input: Tensor, epsilon: number, meanAndVarianceShape: readonly number[]):
|
||||
ProgramInfoLoader => {
|
||||
const metadata = {...computeOutputProgramMetadata, cacheHint: `${epsilon}`};
|
||||
return {
|
||||
...metadata,
|
||||
get: () => createComputeOutputProgramInfo(inferenceHandler, metadata, input, epsilon, meanAndVarianceShape)
|
||||
};
|
||||
};
|
||||
|
||||
const validateInputs = (inputs: Tensor[]): void => {
|
||||
if (!inputs || inputs.length !== 3) {
|
||||
throw new Error('InstanceNormalization requires 3 inputs.');
|
||||
}
|
||||
|
||||
const X = inputs[0];
|
||||
const scale = inputs[1];
|
||||
const B = inputs[2];
|
||||
|
||||
// input should at least have three dimensions - N,C,dim1,...,dimn
|
||||
// other inputs can have only one dimensions
|
||||
if (X.dims.length < 3 || scale.dims.length !== 1 || B.dims.length !== 1) {
|
||||
throw new Error('Invalid input shape.');
|
||||
}
|
||||
if (scale.dims[0] !== X.dims[1] || B.dims[0] !== X.dims[1]) {
|
||||
throw new Error('Input shapes are mismatched.');
|
||||
}
|
||||
if ((X.type !== 'float32' && X.type !== 'float64') || (scale.type !== 'float32' && scale.type !== 'float64') ||
|
||||
(B.type !== 'float32' && B.type !== 'float64')) {
|
||||
throw new Error('Invalid input type.');
|
||||
}
|
||||
if (inputs[0].dims.length !== 4) {
|
||||
throw new Error('Only support 4-D input shape.');
|
||||
}
|
||||
};
|
||||
131
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/matmul-pack.js
generated
vendored
Normal file
131
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/matmul-pack.js
generated
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createPackedMatmulProgramInfoLoader = void 0;
|
||||
const util_1 = require("../../../util");
|
||||
const glsl_source_1 = require("../glsl-source");
|
||||
const types_1 = require("../types");
|
||||
const utils_1 = require("../utils");
|
||||
const fuse_utils_1 = require("./fuse-utils");
|
||||
const matmul_1 = require("./matmul");
|
||||
const createPackedMatmulProgramMetadata = (hasBias, cacheHint) => ({
|
||||
name: 'MatMul (packed)',
|
||||
inputNames: hasBias ? ['A', 'B', 'Bias'] : ['A', 'B'],
|
||||
inputTypes: hasBias ? [types_1.TextureType.packed, types_1.TextureType.packed, types_1.TextureType.packed] :
|
||||
[types_1.TextureType.packed, types_1.TextureType.packed],
|
||||
cacheHint
|
||||
});
|
||||
const createPackedMatmulProgramInfo = (inferenceHandler, metadata, inputs, activationAttributes) => {
|
||||
const hasBias = inputs.length > 2;
|
||||
const processBias = hasBias ? 'value += getBiasForMatmul();' : '';
|
||||
const aShape = inputs[0].dims;
|
||||
const bShape = inputs[1].dims;
|
||||
const outputShape = util_1.BroadcastUtil.calcShape(aShape, bShape, true);
|
||||
const isBroadcast = !util_1.ShapeUtil.areEqual(inputs[0].dims, inputs[1].dims);
|
||||
if (!outputShape) {
|
||||
throw new Error('Can\'t use matmul on the given tensors');
|
||||
}
|
||||
const sharedDim = aShape[aShape.length - 1];
|
||||
const sharedDimIndex = Math.ceil(sharedDim / 2);
|
||||
const aRank = aShape.length;
|
||||
const bRank = bShape.length;
|
||||
const glsl = (0, glsl_source_1.getGlsl)(inferenceHandler.session.backend.glContext.version);
|
||||
const coordsDataType = (0, utils_1.getCoordsDataType)(outputShape.length);
|
||||
const outRank = outputShape.length;
|
||||
const allGlChannels = (0, utils_1.getGlChannels)();
|
||||
const { activationFunction, applyActivation } = (0, fuse_utils_1.getActivationSnippet)(activationAttributes);
|
||||
const getBiasForMatmulSnippet = hasBias ? `${(0, matmul_1.getBiasForMatmul)(coordsDataType, allGlChannels, inputs[2].dims, outputShape, true)}` : '';
|
||||
const getBcastedSamplerForMatmulSnippet = isBroadcast ? `${getBcastSamplerForMatmul(coordsDataType, allGlChannels, inputs, outputShape)}` : '';
|
||||
const getSamplerAInLoopSnippet = isBroadcast ? 'getAAtOutCoordsMatmul(i)' : `getA(${getA(allGlChannels, aRank)})`;
|
||||
const getSamplerBInLoopSnippet = isBroadcast ? 'getBAtOutCoordsMatmul(i)' : `getB(${getB(allGlChannels, bRank)})`;
|
||||
const getOutputCoordsSnippet = isBroadcast ? '' : `${coordsDataType} rc =
|
||||
getOutputCoords(); int lastDim = rc.${allGlChannels[outRank - 1]}; rc.${allGlChannels[outRank - 1]} =
|
||||
rc.${allGlChannels[outRank - 2]}; rc.${allGlChannels[outRank - 2]} = lastDim;
|
||||
`;
|
||||
const shaderSource = `
|
||||
${getBcastedSamplerForMatmulSnippet}
|
||||
${getBiasForMatmulSnippet}
|
||||
${activationFunction}
|
||||
void main() {
|
||||
${getOutputCoordsSnippet}
|
||||
|
||||
vec4 value = vec4(0);
|
||||
for (int i = 0; i < ${sharedDimIndex}; i++) {
|
||||
vec4 a = ${getSamplerAInLoopSnippet};
|
||||
vec4 b = ${getSamplerBInLoopSnippet};
|
||||
|
||||
value += (a.rrbb * b.rgrg);
|
||||
value += (a.ggaa * b.baba);
|
||||
}
|
||||
${processBias}
|
||||
${applyActivation}
|
||||
${glsl.output} = value;
|
||||
}`;
|
||||
return Object.assign(Object.assign({}, metadata), { output: { dims: outputShape, type: inputs[0].type, textureType: types_1.TextureType.packed }, shaderSource, hasMain: true });
|
||||
};
|
||||
const createPackedMatmulProgramInfoLoader = (inferenceHandler, inputs, activationAttributes) => {
|
||||
const metadata = createPackedMatmulProgramMetadata(inputs.length > 2, activationAttributes.activationCacheKey);
|
||||
return Object.assign(Object.assign({}, metadata), { get: () => createPackedMatmulProgramInfo(inferenceHandler, metadata, inputs, activationAttributes) });
|
||||
};
|
||||
exports.createPackedMatmulProgramInfoLoader = createPackedMatmulProgramInfoLoader;
|
||||
function getBcastSamplerForMatmul(coordsDataType, allGlChannels, inputs, outShape) {
|
||||
let unpackedACoordsSnippet = [];
|
||||
let unpackedBCoordsSnippet = [];
|
||||
const inAShape = inputs[0].dims;
|
||||
const inBShape = inputs[1].dims;
|
||||
const inARank = inAShape.length;
|
||||
const inBRank = inBShape.length;
|
||||
const outRank = outShape.length;
|
||||
const rankADiff = outRank - inARank;
|
||||
const rankBDiff = outRank - inBRank;
|
||||
unpackedACoordsSnippet = inAShape.map((s, i) => `coords.${allGlChannels[i + rankADiff]}`);
|
||||
unpackedACoordsSnippet[inARank - 1] = 'i*2';
|
||||
unpackedACoordsSnippet.join(', ');
|
||||
unpackedBCoordsSnippet = inBShape.map((s, i) => `coords.${allGlChannels[i + rankBDiff]}`);
|
||||
unpackedBCoordsSnippet[inBRank - 2] = 'i*2';
|
||||
unpackedBCoordsSnippet.join(', ');
|
||||
const broadcastADims = util_1.BroadcastUtil.getBroadcastDims(inAShape, outShape);
|
||||
const broadcastBDims = util_1.BroadcastUtil.getBroadcastDims(inBShape, outShape);
|
||||
const coordsASnippet = broadcastADims.map(d => `coords.${allGlChannels[d + rankADiff]} = 0;`).join('\n');
|
||||
const coordsBSnippet = broadcastBDims.map(d => `coords.${allGlChannels[d + rankBDiff]} = 0;`).join('\n');
|
||||
const swapDimSnippet = `int lastDim = coords.${allGlChannels[outRank - 1]};
|
||||
coords.${allGlChannels[outRank - 1]} = coords.${allGlChannels[outRank - 2]};
|
||||
coords.${allGlChannels[outRank - 2]} = lastDim;`;
|
||||
const getBcastSamplerMatmulSource = `
|
||||
vec4 getAAtOutCoordsMatmul(int i) {
|
||||
${coordsDataType} coords = getOutputCoords();
|
||||
${swapDimSnippet}
|
||||
${coordsASnippet}
|
||||
vec4 outputValue = getA(${unpackedACoordsSnippet});
|
||||
return outputValue;
|
||||
}
|
||||
|
||||
vec4 getBAtOutCoordsMatmul(int i) {
|
||||
${coordsDataType} coords = getOutputCoords();
|
||||
${swapDimSnippet}
|
||||
${coordsBSnippet}
|
||||
vec4 outputValue = getB(${unpackedBCoordsSnippet});
|
||||
return outputValue;
|
||||
}`;
|
||||
return getBcastSamplerMatmulSource;
|
||||
}
|
||||
function getA(allGlChannels, rank) {
|
||||
let res = '';
|
||||
for (let i = 0; i < rank - 2; i++) {
|
||||
res += `rc.${allGlChannels[i]}, `;
|
||||
}
|
||||
res += `rc.${allGlChannels[rank - 2]}, ` +
|
||||
'i*2';
|
||||
return res;
|
||||
}
|
||||
function getB(allGlChannels, rank) {
|
||||
let res = '';
|
||||
for (let i = 0; i < rank - 2; i++) {
|
||||
res += `rc.${allGlChannels[i]}, `;
|
||||
}
|
||||
res += 'i*2, ' +
|
||||
`rc.${allGlChannels[rank - 1]}`;
|
||||
return res;
|
||||
}
|
||||
//# sourceMappingURL=matmul-pack.js.map
|
||||
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/matmul-pack.js.map
generated
vendored
Normal file
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/matmul-pack.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
164
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/matmul-pack.ts
generated
vendored
Normal file
164
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/matmul-pack.ts
generated
vendored
Normal file
@@ -0,0 +1,164 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import {Tensor} from '../../../tensor';
|
||||
import {BroadcastUtil, ShapeUtil} from '../../../util';
|
||||
import {getGlsl} from '../glsl-source';
|
||||
import {WebGLInferenceHandler} from '../inference-handler';
|
||||
import {ProgramInfo, ProgramInfoLoader, ProgramMetadata, TextureType} from '../types';
|
||||
import {getCoordsDataType, getGlChannels} from '../utils';
|
||||
|
||||
import {getActivationSnippet, InternalActivationAttributes} from './fuse-utils';
|
||||
import {getBiasForMatmul} from './matmul';
|
||||
|
||||
const createPackedMatmulProgramMetadata = (hasBias: boolean, cacheHint: string) => ({
|
||||
name: 'MatMul (packed)',
|
||||
inputNames: hasBias ? ['A', 'B', 'Bias'] : ['A', 'B'],
|
||||
inputTypes: hasBias ? [TextureType.packed, TextureType.packed, TextureType.packed] :
|
||||
[TextureType.packed, TextureType.packed],
|
||||
cacheHint
|
||||
});
|
||||
|
||||
const createPackedMatmulProgramInfo =
|
||||
(inferenceHandler: WebGLInferenceHandler, metadata: ProgramMetadata, inputs: Tensor[],
|
||||
activationAttributes: InternalActivationAttributes): ProgramInfo => {
|
||||
const hasBias = inputs.length > 2;
|
||||
const processBias = hasBias ? 'value += getBiasForMatmul();' : '';
|
||||
const aShape = inputs[0].dims;
|
||||
const bShape = inputs[1].dims;
|
||||
const outputShape = BroadcastUtil.calcShape(aShape, bShape, true);
|
||||
const isBroadcast = !ShapeUtil.areEqual(inputs[0].dims, inputs[1].dims);
|
||||
|
||||
if (!outputShape) {
|
||||
throw new Error('Can\'t use matmul on the given tensors');
|
||||
}
|
||||
const sharedDim = aShape[aShape.length - 1];
|
||||
const sharedDimIndex = Math.ceil(sharedDim / 2);
|
||||
const aRank = aShape.length;
|
||||
const bRank = bShape.length;
|
||||
|
||||
const glsl = getGlsl(inferenceHandler.session.backend.glContext.version);
|
||||
const coordsDataType = getCoordsDataType(outputShape.length);
|
||||
const outRank = outputShape.length;
|
||||
const allGlChannels = getGlChannels();
|
||||
const {activationFunction, applyActivation} = getActivationSnippet(activationAttributes);
|
||||
|
||||
const getBiasForMatmulSnippet =
|
||||
hasBias ? `${getBiasForMatmul(coordsDataType, allGlChannels, inputs[2].dims, outputShape, true)}` : '';
|
||||
|
||||
const getBcastedSamplerForMatmulSnippet =
|
||||
isBroadcast ? `${getBcastSamplerForMatmul(coordsDataType, allGlChannels, inputs, outputShape)}` : '';
|
||||
|
||||
const getSamplerAInLoopSnippet = isBroadcast ? 'getAAtOutCoordsMatmul(i)' : `getA(${getA(allGlChannels, aRank)})`;
|
||||
const getSamplerBInLoopSnippet = isBroadcast ? 'getBAtOutCoordsMatmul(i)' : `getB(${getB(allGlChannels, bRank)})`;
|
||||
const getOutputCoordsSnippet = isBroadcast ? '' : `${coordsDataType} rc =
|
||||
getOutputCoords(); int lastDim = rc.${allGlChannels[outRank - 1]}; rc.${allGlChannels[outRank - 1]} =
|
||||
rc.${allGlChannels[outRank - 2]}; rc.${allGlChannels[outRank - 2]} = lastDim;
|
||||
`;
|
||||
const shaderSource = `
|
||||
${getBcastedSamplerForMatmulSnippet}
|
||||
${getBiasForMatmulSnippet}
|
||||
${activationFunction}
|
||||
void main() {
|
||||
${getOutputCoordsSnippet}
|
||||
|
||||
vec4 value = vec4(0);
|
||||
for (int i = 0; i < ${sharedDimIndex}; i++) {
|
||||
vec4 a = ${getSamplerAInLoopSnippet};
|
||||
vec4 b = ${getSamplerBInLoopSnippet};
|
||||
|
||||
value += (a.rrbb * b.rgrg);
|
||||
value += (a.ggaa * b.baba);
|
||||
}
|
||||
${processBias}
|
||||
${applyActivation}
|
||||
${glsl.output} = value;
|
||||
}`;
|
||||
return {
|
||||
...metadata,
|
||||
output: {dims: outputShape, type: inputs[0].type, textureType: TextureType.packed},
|
||||
shaderSource,
|
||||
hasMain: true
|
||||
};
|
||||
};
|
||||
|
||||
export const createPackedMatmulProgramInfoLoader =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: Tensor[],
|
||||
activationAttributes: InternalActivationAttributes): ProgramInfoLoader => {
|
||||
const metadata = createPackedMatmulProgramMetadata(inputs.length > 2, activationAttributes.activationCacheKey);
|
||||
return {
|
||||
...metadata,
|
||||
get: () => createPackedMatmulProgramInfo(inferenceHandler, metadata, inputs, activationAttributes)
|
||||
};
|
||||
};
|
||||
|
||||
function getBcastSamplerForMatmul(
|
||||
coordsDataType: string, allGlChannels: readonly string[], inputs: Tensor[], outShape: readonly number[]): string {
|
||||
let unpackedACoordsSnippet = [];
|
||||
let unpackedBCoordsSnippet = [];
|
||||
|
||||
const inAShape = inputs[0].dims;
|
||||
const inBShape = inputs[1].dims;
|
||||
|
||||
const inARank = inAShape.length;
|
||||
const inBRank = inBShape.length;
|
||||
|
||||
const outRank = outShape.length;
|
||||
const rankADiff = outRank - inARank;
|
||||
const rankBDiff = outRank - inBRank;
|
||||
|
||||
unpackedACoordsSnippet = inAShape.map((s, i) => `coords.${allGlChannels[i + rankADiff]}`);
|
||||
unpackedACoordsSnippet[inARank - 1] = 'i*2';
|
||||
unpackedACoordsSnippet.join(', ');
|
||||
unpackedBCoordsSnippet = inBShape.map((s, i) => `coords.${allGlChannels[i + rankBDiff]}`);
|
||||
unpackedBCoordsSnippet[inBRank - 2] = 'i*2';
|
||||
unpackedBCoordsSnippet.join(', ');
|
||||
|
||||
const broadcastADims = BroadcastUtil.getBroadcastDims(inAShape, outShape);
|
||||
const broadcastBDims = BroadcastUtil.getBroadcastDims(inBShape, outShape);
|
||||
|
||||
const coordsASnippet = broadcastADims.map(d => `coords.${allGlChannels[d + rankADiff]} = 0;`).join('\n');
|
||||
const coordsBSnippet = broadcastBDims.map(d => `coords.${allGlChannels[d + rankBDiff]} = 0;`).join('\n');
|
||||
const swapDimSnippet = `int lastDim = coords.${allGlChannels[outRank - 1]};
|
||||
coords.${allGlChannels[outRank - 1]} = coords.${allGlChannels[outRank - 2]};
|
||||
coords.${allGlChannels[outRank - 2]} = lastDim;`;
|
||||
|
||||
const getBcastSamplerMatmulSource = `
|
||||
vec4 getAAtOutCoordsMatmul(int i) {
|
||||
${coordsDataType} coords = getOutputCoords();
|
||||
${swapDimSnippet}
|
||||
${coordsASnippet}
|
||||
vec4 outputValue = getA(${unpackedACoordsSnippet});
|
||||
return outputValue;
|
||||
}
|
||||
|
||||
vec4 getBAtOutCoordsMatmul(int i) {
|
||||
${coordsDataType} coords = getOutputCoords();
|
||||
${swapDimSnippet}
|
||||
${coordsBSnippet}
|
||||
vec4 outputValue = getB(${unpackedBCoordsSnippet});
|
||||
return outputValue;
|
||||
}`;
|
||||
|
||||
return getBcastSamplerMatmulSource;
|
||||
}
|
||||
|
||||
function getA(allGlChannels: string[], rank: number): string {
|
||||
let res = '';
|
||||
for (let i = 0; i < rank - 2; i++) {
|
||||
res += `rc.${allGlChannels[i]}, `;
|
||||
}
|
||||
res += `rc.${allGlChannels[rank - 2]}, ` +
|
||||
'i*2';
|
||||
return res;
|
||||
}
|
||||
|
||||
function getB(allGlChannels: string[], rank: number): string {
|
||||
let res = '';
|
||||
for (let i = 0; i < rank - 2; i++) {
|
||||
res += `rc.${allGlChannels[i]}, `;
|
||||
}
|
||||
res += 'i*2, ' +
|
||||
`rc.${allGlChannels[rank - 1]}`;
|
||||
return res;
|
||||
}
|
||||
123
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/matmul.js
generated
vendored
Normal file
123
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/matmul.js
generated
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getBiasForMatmul = exports.createMatmulProgramInfoLoader = exports.parseMatMulAttributes = exports.matMul = void 0;
|
||||
const util_1 = require("../../../util");
|
||||
const types_1 = require("../types");
|
||||
const utils_1 = require("../utils");
|
||||
const fuse_utils_1 = require("./fuse-utils");
|
||||
const matmul_pack_1 = require("./matmul-pack");
|
||||
const matMul = (inferenceHandler, inputs, attributes) => {
|
||||
validateInputs(inputs);
|
||||
if (inferenceHandler.session.pack) {
|
||||
return [inferenceHandler.run((0, matmul_pack_1.createPackedMatmulProgramInfoLoader)(inferenceHandler, inputs, attributes), inputs)];
|
||||
}
|
||||
else {
|
||||
return [inferenceHandler.run(createMatmulProgramInfoLoader(inputs, attributes), inputs)];
|
||||
}
|
||||
};
|
||||
exports.matMul = matMul;
|
||||
const parseMatMulAttributes = (node) => (0, fuse_utils_1.parseInternalActivationAttributes)(node.attributes);
|
||||
exports.parseMatMulAttributes = parseMatMulAttributes;
|
||||
const createMatmulProgramMetadata = (hasBias, cacheHint) => ({
|
||||
name: 'MatMul',
|
||||
inputNames: hasBias ? ['A', 'B', 'Bias'] : ['A', 'B'],
|
||||
inputTypes: hasBias ? [types_1.TextureType.unpacked, types_1.TextureType.unpacked, types_1.TextureType.unpacked] :
|
||||
[types_1.TextureType.unpacked, types_1.TextureType.unpacked],
|
||||
cacheHint
|
||||
});
|
||||
function createMatmulProgramInfo(metadata, inputs, activationAttributes) {
|
||||
const aShape = inputs[0].dims;
|
||||
const bShape = inputs[1].dims;
|
||||
const outputShape = util_1.BroadcastUtil.calcShape(aShape, bShape, true);
|
||||
if (!outputShape) {
|
||||
throw new Error('Can\'t use matmul on the given tensors');
|
||||
}
|
||||
const coordsDataType = (0, utils_1.getCoordsDataType)(outputShape.length);
|
||||
const allGlChannels = (0, utils_1.getGlChannels)();
|
||||
const { activationFunction, applyActivation } = (0, fuse_utils_1.getActivationSnippet)(activationAttributes);
|
||||
const hasBias = inputs.length > 2;
|
||||
const processBias = hasBias ? 'value += getBiasForMatmul();' : '';
|
||||
const getBiasForMatmulSnippet = hasBias ? `${getBiasForMatmul(coordsDataType, allGlChannels, inputs[2].dims, outputShape, false)}` : '';
|
||||
const rank = outputShape.length;
|
||||
const arank = aShape.length;
|
||||
const brank = bShape.length;
|
||||
const sharedDim = aShape[aShape.length - 1];
|
||||
const shaderSource = `
|
||||
${activationFunction}
|
||||
${getBiasForMatmulSnippet}
|
||||
float process(int indices[${rank}]) {
|
||||
int a[${arank}];
|
||||
int b[${brank}];
|
||||
bcastMatmulIndices_A(indices, a);
|
||||
bcastMatmulIndices_B(indices, b);
|
||||
|
||||
float value;
|
||||
for (int k=0; k<${sharedDim}; ++k) {
|
||||
a[${arank - 1}] = k;
|
||||
b[${brank - 2}] = k;
|
||||
value += _A(a) * _B(b);
|
||||
}
|
||||
${processBias}
|
||||
${applyActivation}
|
||||
return value;
|
||||
}`;
|
||||
return Object.assign(Object.assign({}, metadata), { output: { dims: outputShape, type: inputs[0].type, textureType: types_1.TextureType.unpacked }, shaderSource });
|
||||
}
|
||||
function createMatmulProgramInfoLoader(inputs, activationAttributes) {
|
||||
const metadata = createMatmulProgramMetadata(inputs.length > 2, activationAttributes.activationCacheKey);
|
||||
return Object.assign(Object.assign({}, metadata), { get: () => createMatmulProgramInfo(metadata, inputs, activationAttributes) });
|
||||
}
|
||||
exports.createMatmulProgramInfoLoader = createMatmulProgramInfoLoader;
|
||||
const validateInputs = (inputs) => {
|
||||
if (!inputs || inputs.length !== 2) {
|
||||
throw new Error('MatMul requires 2 inputs.');
|
||||
}
|
||||
if (inputs[0].dims[inputs[0].dims.length - 1] !== inputs[1].dims[inputs[1].dims.length - 2]) {
|
||||
throw new Error('shared dimension does not match.');
|
||||
}
|
||||
if ((inputs[0].type !== 'float32' && inputs[0].type !== 'float64') ||
|
||||
(inputs[1].type !== 'float32' && inputs[1].type !== 'float64')) {
|
||||
throw new Error('inputs should be float type');
|
||||
}
|
||||
if (inputs[0].type !== inputs[1].type) {
|
||||
throw new Error('inputs types should match');
|
||||
}
|
||||
};
|
||||
function getBiasForMatmul(coordsDataType, allGlChannels, inShape, outShape, isPacked) {
|
||||
let unpackedCoordsSnippet = '';
|
||||
const inRank = inShape.length;
|
||||
const outRank = outShape.length;
|
||||
const rankDiff = outRank - inRank;
|
||||
if (outRank < 2 && inRank > 0) {
|
||||
unpackedCoordsSnippet = 'coords';
|
||||
}
|
||||
else {
|
||||
unpackedCoordsSnippet = inShape.map((s, i) => `coords.${allGlChannels[i + rankDiff]}`).join(', ');
|
||||
}
|
||||
const broadcastDims = util_1.BroadcastUtil.getBroadcastDims(inShape, outShape);
|
||||
const coordsSnippet = broadcastDims.map(d => `coords.${allGlChannels[d + rankDiff]} = 0;`).join('\n');
|
||||
const inSize = util_1.ShapeUtil.size(inShape);
|
||||
const isInputScalar = inSize === 1;
|
||||
let output = 'vec4(outputValue.xx, outputValue.yy)';
|
||||
if (isInputScalar) {
|
||||
output = 'vec4(outputValue.x)';
|
||||
}
|
||||
const getBiasForMatmulSource = isPacked ? `
|
||||
vec4 getBiasForMatmul() {
|
||||
${coordsDataType} coords = getOutputCoords();
|
||||
${coordsSnippet}
|
||||
vec4 outputValue = getBias(${unpackedCoordsSnippet});
|
||||
return ${output};
|
||||
}` :
|
||||
`
|
||||
float getBiasForMatmul() {
|
||||
${coordsDataType} coords = getOutputCoords();
|
||||
${coordsSnippet}
|
||||
return getBias(coords.x);
|
||||
}`;
|
||||
return getBiasForMatmulSource;
|
||||
}
|
||||
exports.getBiasForMatmul = getBiasForMatmul;
|
||||
//# sourceMappingURL=matmul.js.map
|
||||
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/matmul.js.map
generated
vendored
Normal file
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/matmul.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"matmul.js","sourceRoot":"","sources":["matmul.ts"],"names":[],"mappings":"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"}
|
||||
145
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/matmul.ts
generated
vendored
Normal file
145
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/matmul.ts
generated
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import {Graph} from '../../../graph';
|
||||
import {OperatorImplementation, OperatorInitialization} from '../../../operators';
|
||||
import {Tensor} from '../../../tensor';
|
||||
import {BroadcastUtil, ShapeUtil} from '../../../util';
|
||||
import {WebGLInferenceHandler} from '../inference-handler';
|
||||
import {ProgramInfo, ProgramInfoLoader, ProgramMetadata, TextureType} from '../types';
|
||||
import {getCoordsDataType, getGlChannels} from '../utils';
|
||||
|
||||
import {getActivationSnippet, InternalActivationAttributes, parseInternalActivationAttributes} from './fuse-utils';
|
||||
import {createPackedMatmulProgramInfoLoader} from './matmul-pack';
|
||||
|
||||
export const matMul: OperatorImplementation<InternalActivationAttributes> =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: InternalActivationAttributes): Tensor[] => {
|
||||
validateInputs(inputs);
|
||||
|
||||
if (inferenceHandler.session.pack) {
|
||||
return [inferenceHandler.run(
|
||||
createPackedMatmulProgramInfoLoader(inferenceHandler, inputs, attributes), inputs)];
|
||||
} else {
|
||||
return [inferenceHandler.run(createMatmulProgramInfoLoader(inputs, attributes), inputs)];
|
||||
}
|
||||
};
|
||||
|
||||
export const parseMatMulAttributes: OperatorInitialization<InternalActivationAttributes> =
|
||||
(node: Graph.Node): InternalActivationAttributes => parseInternalActivationAttributes(node.attributes);
|
||||
|
||||
const createMatmulProgramMetadata = (hasBias: boolean, cacheHint: string) => ({
|
||||
name: 'MatMul',
|
||||
inputNames: hasBias ? ['A', 'B', 'Bias'] : ['A', 'B'],
|
||||
inputTypes: hasBias ? [TextureType.unpacked, TextureType.unpacked, TextureType.unpacked] :
|
||||
[TextureType.unpacked, TextureType.unpacked],
|
||||
cacheHint
|
||||
});
|
||||
|
||||
function createMatmulProgramInfo(
|
||||
metadata: ProgramMetadata, inputs: Tensor[], activationAttributes: InternalActivationAttributes): ProgramInfo {
|
||||
const aShape = inputs[0].dims;
|
||||
const bShape = inputs[1].dims;
|
||||
const outputShape = BroadcastUtil.calcShape(aShape, bShape, true);
|
||||
if (!outputShape) {
|
||||
throw new Error('Can\'t use matmul on the given tensors');
|
||||
}
|
||||
const coordsDataType = getCoordsDataType(outputShape.length);
|
||||
const allGlChannels = getGlChannels();
|
||||
const {activationFunction, applyActivation} = getActivationSnippet(activationAttributes);
|
||||
|
||||
const hasBias = inputs.length > 2;
|
||||
const processBias = hasBias ? 'value += getBiasForMatmul();' : '';
|
||||
const getBiasForMatmulSnippet =
|
||||
hasBias ? `${getBiasForMatmul(coordsDataType, allGlChannels, inputs[2].dims, outputShape, false)}` : '';
|
||||
|
||||
const rank = outputShape.length;
|
||||
const arank = aShape.length;
|
||||
const brank = bShape.length;
|
||||
const sharedDim = aShape[aShape.length - 1];
|
||||
const shaderSource = `
|
||||
${activationFunction}
|
||||
${getBiasForMatmulSnippet}
|
||||
float process(int indices[${rank}]) {
|
||||
int a[${arank}];
|
||||
int b[${brank}];
|
||||
bcastMatmulIndices_A(indices, a);
|
||||
bcastMatmulIndices_B(indices, b);
|
||||
|
||||
float value;
|
||||
for (int k=0; k<${sharedDim}; ++k) {
|
||||
a[${arank - 1}] = k;
|
||||
b[${brank - 2}] = k;
|
||||
value += _A(a) * _B(b);
|
||||
}
|
||||
${processBias}
|
||||
${applyActivation}
|
||||
return value;
|
||||
}`;
|
||||
return {
|
||||
...metadata,
|
||||
output: {dims: outputShape, type: inputs[0].type, textureType: TextureType.unpacked},
|
||||
shaderSource,
|
||||
};
|
||||
}
|
||||
|
||||
export function createMatmulProgramInfoLoader(
|
||||
inputs: Tensor[], activationAttributes: InternalActivationAttributes): ProgramInfoLoader {
|
||||
const metadata = createMatmulProgramMetadata(inputs.length > 2, activationAttributes.activationCacheKey);
|
||||
return {...metadata, get: () => createMatmulProgramInfo(metadata, inputs, activationAttributes)};
|
||||
}
|
||||
|
||||
const validateInputs = (inputs: Tensor[]): void => {
|
||||
if (!inputs || inputs.length !== 2) {
|
||||
throw new Error('MatMul requires 2 inputs.');
|
||||
}
|
||||
|
||||
if (inputs[0].dims[inputs[0].dims.length - 1] !== inputs[1].dims[inputs[1].dims.length - 2]) {
|
||||
throw new Error('shared dimension does not match.');
|
||||
}
|
||||
|
||||
if ((inputs[0].type !== 'float32' && inputs[0].type !== 'float64') ||
|
||||
(inputs[1].type !== 'float32' && inputs[1].type !== 'float64')) {
|
||||
throw new Error('inputs should be float type');
|
||||
}
|
||||
|
||||
if (inputs[0].type !== inputs[1].type) {
|
||||
throw new Error('inputs types should match');
|
||||
}
|
||||
};
|
||||
|
||||
export function getBiasForMatmul(
|
||||
coordsDataType: string, allGlChannels: readonly string[], inShape: readonly number[], outShape: readonly number[],
|
||||
isPacked: boolean): string {
|
||||
let unpackedCoordsSnippet = '';
|
||||
const inRank = inShape.length;
|
||||
const outRank = outShape.length;
|
||||
const rankDiff = outRank - inRank;
|
||||
if (outRank < 2 && inRank > 0) {
|
||||
unpackedCoordsSnippet = 'coords';
|
||||
} else {
|
||||
unpackedCoordsSnippet = inShape.map((s, i) => `coords.${allGlChannels[i + rankDiff]}`).join(', ');
|
||||
}
|
||||
const broadcastDims = BroadcastUtil.getBroadcastDims(inShape, outShape);
|
||||
const coordsSnippet = broadcastDims.map(d => `coords.${allGlChannels[d + rankDiff]} = 0;`).join('\n');
|
||||
const inSize = ShapeUtil.size(inShape);
|
||||
const isInputScalar = inSize === 1;
|
||||
let output = 'vec4(outputValue.xx, outputValue.yy)';
|
||||
if (isInputScalar) {
|
||||
output = 'vec4(outputValue.x)';
|
||||
}
|
||||
const getBiasForMatmulSource = isPacked ? `
|
||||
vec4 getBiasForMatmul() {
|
||||
${coordsDataType} coords = getOutputCoords();
|
||||
${coordsSnippet}
|
||||
vec4 outputValue = getBias(${unpackedCoordsSnippet});
|
||||
return ${output};
|
||||
}` :
|
||||
`
|
||||
float getBiasForMatmul() {
|
||||
${coordsDataType} coords = getOutputCoords();
|
||||
${coordsSnippet}
|
||||
return getBias(coords.x);
|
||||
}`;
|
||||
|
||||
return getBiasForMatmulSource;
|
||||
}
|
||||
120
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/pack.js
generated
vendored
Normal file
120
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/pack.js
generated
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createPackProgramInfoLoader = void 0;
|
||||
const glsl_source_1 = require("../glsl-source");
|
||||
const types_1 = require("../types");
|
||||
const utils_1 = require("../utils");
|
||||
const packing_utils_1 = require("./packing-utils");
|
||||
const packProgramMetadata = {
|
||||
name: 'pack',
|
||||
inputNames: ['A'],
|
||||
inputTypes: [types_1.TextureType.unpackedReversed]
|
||||
};
|
||||
const createPackProgramInfo = (handler, input) => {
|
||||
const glsl = (0, glsl_source_1.getGlsl)(handler.session.backend.glContext.version);
|
||||
const inputShape = input.dims;
|
||||
const inputRank = inputShape.length;
|
||||
// createTextureLayoutFromShape won't change output rank. Need to verify by running tests
|
||||
const outputRank = input.dims.length;
|
||||
const coordsDataType = (0, utils_1.getCoordsDataType)(outputRank);
|
||||
const channels = (0, packing_utils_1.getChannels)('rc', outputRank);
|
||||
const setup = getSetup(outputRank, channels, inputShape[inputShape.length - 2], inputShape[inputShape.length - 1]);
|
||||
let reversedInputWH;
|
||||
if (inputRank === 0) {
|
||||
reversedInputWH = [1, 1];
|
||||
}
|
||||
else if (inputRank === 1) {
|
||||
reversedInputWH = [inputShape[0], 1];
|
||||
}
|
||||
else {
|
||||
reversedInputWH = [inputShape[outputRank - 1], inputShape[outputRank - 2]];
|
||||
}
|
||||
const outOfBoundsCondition = getOutOfBoundsCondition(outputRank, reversedInputWH, channels);
|
||||
const output = getOutput(inputShape, channels);
|
||||
const shaderSource = `
|
||||
void main() {
|
||||
${coordsDataType} rc = getOutputCoords();
|
||||
|
||||
if(${outOfBoundsCondition}) {
|
||||
${glsl.output} = vec4(0);
|
||||
} else {
|
||||
${setup}
|
||||
|
||||
${glsl.output} = vec4(${output});
|
||||
}
|
||||
}
|
||||
`;
|
||||
return Object.assign(Object.assign({}, packProgramMetadata), { hasMain: true, output: { dims: input.dims, type: input.type, textureType: types_1.TextureType.packed }, shaderSource });
|
||||
};
|
||||
const createPackProgramInfoLoader = (handler, input) => (Object.assign(Object.assign({}, packProgramMetadata), { get: () => createPackProgramInfo(handler, input) }));
|
||||
exports.createPackProgramInfoLoader = createPackProgramInfoLoader;
|
||||
/**
|
||||
* check output coordinate location and return false if it is outside input's width/height boundary
|
||||
*/
|
||||
function getOutOfBoundsCondition(rank, shape, dims) {
|
||||
if (rank === 0) {
|
||||
return 'false';
|
||||
}
|
||||
if (rank === 1) {
|
||||
return `rc > ${shape[0]}`;
|
||||
}
|
||||
let cond = '';
|
||||
for (let i = rank - 2; i < rank; i++) {
|
||||
cond += `${dims[i]} >= ${shape[i - rank + 2]}`;
|
||||
if (i < rank - 1) {
|
||||
cond += '||';
|
||||
}
|
||||
}
|
||||
return cond;
|
||||
}
|
||||
/**
|
||||
* code snippet to sample input texture with output coordiantes
|
||||
*/
|
||||
function getOutput(shape, dims) {
|
||||
const rank = shape.length;
|
||||
if (rank === 0) {
|
||||
return 'getA(), 0, 0, 0';
|
||||
}
|
||||
if (rank === 1) {
|
||||
return `getA(rc),
|
||||
rc + 1 >= ${shape[0]} ? 0. : getA(rc + 1),
|
||||
0, 0`;
|
||||
}
|
||||
const coord00 = 'r, c';
|
||||
const coord01 = 'r, cp1';
|
||||
const coord10 = 'rp1, c';
|
||||
const coord11 = 'rp1, cp1';
|
||||
let D = '';
|
||||
if (rank > 2) {
|
||||
for (let i = 0; i < rank - 2; ++i) {
|
||||
D = D + `${dims[i]},`;
|
||||
}
|
||||
}
|
||||
return `getA(${D}${coord00}),
|
||||
rEdge ? 0. : getA(${D}${coord10}),
|
||||
cEdge ? 0. : getA(${D}${coord01}),
|
||||
rEdge || cEdge ? 0. : getA(${D}${coord11})`;
|
||||
}
|
||||
/**
|
||||
* code snippet to setup 4 coordinates and edge conditions
|
||||
*/
|
||||
function getSetup(rank, dims, rows, cols) {
|
||||
if (rank === 0 || rank === 1) {
|
||||
return '';
|
||||
}
|
||||
// rank >= 2 for width+height pack.
|
||||
else {
|
||||
const setup = `
|
||||
int r = ${dims[rank - 2]};
|
||||
int c = ${dims[rank - 1]};
|
||||
int rp1 = ${dims[rank - 2]} + 1;
|
||||
int cp1 = ${dims[rank - 1]} + 1;
|
||||
bool rEdge = rp1 >= ${cols};
|
||||
bool cEdge = cp1 >= ${rows};
|
||||
`;
|
||||
return setup;
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=pack.js.map
|
||||
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/pack.js.map
generated
vendored
Normal file
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/pack.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"pack.js","sourceRoot":"","sources":["pack.ts"],"names":[],"mappings":";AAAA,4DAA4D;AAC5D,kCAAkC;;;AAGlC,gDAAuC;AAEvC,oCAAqE;AACrE,oCAA2C;AAE3C,mDAA4C;AAE5C,MAAM,mBAAmB,GAAG;IAC1B,IAAI,EAAE,MAAM;IACZ,UAAU,EAAE,CAAC,GAAG,CAAC;IACjB,UAAU,EAAE,CAAC,mBAAW,CAAC,gBAAgB,CAAC;CAC3C,CAAC;AAEF,MAAM,qBAAqB,GAAG,CAAC,OAA8B,EAAE,KAAa,EAAe,EAAE;IAC3F,MAAM,IAAI,GAAG,IAAA,qBAAO,EAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IAChE,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC;IAE9B,MAAM,SAAS,GAAG,UAAU,CAAC,MAAM,CAAC;IACpC,yFAAyF;IACzF,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;IAErC,MAAM,cAAc,GAAG,IAAA,yBAAiB,EAAC,UAAU,CAAC,CAAC;IACrD,MAAM,QAAQ,GAAG,IAAA,2BAAW,EAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAC/C,MAAM,KAAK,GAAG,QAAQ,CAAC,UAAU,EAAE,QAAQ,EAAE,UAAU,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC;IAEnH,IAAI,eAAe,CAAC;IACpB,IAAI,SAAS,KAAK,CAAC,EAAE;QACnB,eAAe,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;KAC1B;SAAM,IAAI,SAAS,KAAK,CAAC,EAAE;QAC1B,eAAe,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;KACtC;SAAM;QACL,eAAe,GAAG,CAAC,UAAU,CAAC,UAAU,GAAG,CAAC,CAAC,EAAE,UAAU,CAAC,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC;KAC5E;IACD,MAAM,oBAAoB,GAAG,uBAAuB,CAAC,UAAU,EAAE,eAAe,EAAE,QAAQ,CAAC,CAAC;IAC5F,MAAM,MAAM,GAAG,SAAS,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IAE/C,MAAM,YAAY,GAAG;;YAEX,cAAc;;eAEX,oBAAoB;cACrB,IAAI,CAAC,MAAM;;cAEX,KAAK;;cAEL,IAAI,CAAC,MAAM,WAAW,MAAM;;;OAGnC,CAAC;IACN,uCACK,mBAAmB,KACtB,OAAO,EAAE,IAAI,EACb,MAAM,EAAE,EAAC,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,WAAW,EAAE,mBAAW,CAAC,MAAM,EAAC,EAC7E,YAAY,IACZ;AACJ,CAAC,CAAC;AAEK,MAAM,2BAA2B,GAAG,CAAC,OAA8B,EAAE,KAAa,EAAqB,EAAE,CAC5G,iCAAK,mBAAmB,KAAE,GAAG,EAAE,GAAG,EAAE,CAAC,qBAAqB,CAAC,OAAO,EAAE,KAAK,CAAC,IAAE,CAAC;AADpE,QAAA,2BAA2B,+BACyC;AAEjF;;GAEG;AACH,SAAS,uBAAuB,CAAC,IAAY,EAAE,KAAwB,EAAE,IAAc;IACrF,IAAI,IAAI,KAAK,CAAC,EAAE;QACd,OAAO,OAAO,CAAC;KAChB;IACD,IAAI,IAAI,KAAK,CAAC,EAAE;QACd,OAAO,QAAQ,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;KAC3B;IAED,IAAI,IAAI,GAAG,EAAE,CAAC;IACd,KAAK,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,EAAE,EAAE;QACpC,IAAI,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,EAAE,CAAC;QAC/C,IAAI,CAAC,GAAG,IAAI,GAAG,CAAC,EAAE;YAChB,IAAI,IAAI,IAAI,CAAC;SACd;KACF;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,SAAS,SAAS,CAAC,KAAwB,EAAE,IAAc;IACzD,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC;IAE1B,IAAI,IAAI,KAAK,CAAC,EAAE;QACd,OAAO,iBAAiB,CAAC;KAC1B;IAED,IAAI,IAAI,KAAK,CAAC,EAAE;QACd,OAAO;wBACa,KAAK,CAAC,CAAC,CAAC;iBACf,CAAC;KACf;IAED,MAAM,OAAO,GAAG,MAAM,CAAC;IACvB,MAAM,OAAO,GAAG,QAAQ,CAAC;IACzB,MAAM,OAAO,GAAG,QAAQ,CAAC;IACzB,MAAM,OAAO,GAAG,UAAU,CAAC;IAC3B,IAAI,CAAC,GAAG,EAAE,CAAC;IACX,IAAI,IAAI,GAAG,CAAC,EAAE;QACZ,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,EAAE,EAAE,CAAC,EAAE;YACjC,CAAC,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC;SACvB;KACF;IACD,OAAO,QAAQ,CAAC,GAAG,OAAO;8BACE,CAAC,GAAG,OAAO;8BACX,CAAC,GAAG,OAAO;uCACF,CAAC,GAAG,OAAO,GAAG,CAAC;AACtD,CAAC;AAED;;GAEG;AACH,SAAS,QAAQ,CAAC,IAAY,EAAE,IAAc,EAAE,IAAY,EAAE,IAAY;IACxE,IAAI,IAAI,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,EAAE;QAC5B,OAAO,EAAE,CAAC;KACX;IACD,mCAAmC;SAC9B;QACH,MAAM,KAAK,GAAG;cACJ,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;cACd,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;gBACZ,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;gBACd,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;0BACJ,IAAI;0BACJ,IAAI;KACzB,CAAC;QACF,OAAO,KAAK,CAAC;KACd;AACH,CAAC"}
|
||||
138
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/pack.ts
generated
vendored
Normal file
138
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/pack.ts
generated
vendored
Normal file
@@ -0,0 +1,138 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import {Tensor} from '../../../tensor';
|
||||
import {getGlsl} from '../glsl-source';
|
||||
import {WebGLInferenceHandler} from '../inference-handler';
|
||||
import {ProgramInfo, ProgramInfoLoader, TextureType} from '../types';
|
||||
import {getCoordsDataType} from '../utils';
|
||||
|
||||
import {getChannels} from './packing-utils';
|
||||
|
||||
const packProgramMetadata = {
|
||||
name: 'pack',
|
||||
inputNames: ['A'],
|
||||
inputTypes: [TextureType.unpackedReversed]
|
||||
};
|
||||
|
||||
const createPackProgramInfo = (handler: WebGLInferenceHandler, input: Tensor): ProgramInfo => {
|
||||
const glsl = getGlsl(handler.session.backend.glContext.version);
|
||||
const inputShape = input.dims;
|
||||
|
||||
const inputRank = inputShape.length;
|
||||
// createTextureLayoutFromShape won't change output rank. Need to verify by running tests
|
||||
const outputRank = input.dims.length;
|
||||
|
||||
const coordsDataType = getCoordsDataType(outputRank);
|
||||
const channels = getChannels('rc', outputRank);
|
||||
const setup = getSetup(outputRank, channels, inputShape[inputShape.length - 2], inputShape[inputShape.length - 1]);
|
||||
|
||||
let reversedInputWH;
|
||||
if (inputRank === 0) {
|
||||
reversedInputWH = [1, 1];
|
||||
} else if (inputRank === 1) {
|
||||
reversedInputWH = [inputShape[0], 1];
|
||||
} else {
|
||||
reversedInputWH = [inputShape[outputRank - 1], inputShape[outputRank - 2]];
|
||||
}
|
||||
const outOfBoundsCondition = getOutOfBoundsCondition(outputRank, reversedInputWH, channels);
|
||||
const output = getOutput(inputShape, channels);
|
||||
|
||||
const shaderSource = `
|
||||
void main() {
|
||||
${coordsDataType} rc = getOutputCoords();
|
||||
|
||||
if(${outOfBoundsCondition}) {
|
||||
${glsl.output} = vec4(0);
|
||||
} else {
|
||||
${setup}
|
||||
|
||||
${glsl.output} = vec4(${output});
|
||||
}
|
||||
}
|
||||
`;
|
||||
return {
|
||||
...packProgramMetadata,
|
||||
hasMain: true,
|
||||
output: {dims: input.dims, type: input.type, textureType: TextureType.packed},
|
||||
shaderSource
|
||||
};
|
||||
};
|
||||
|
||||
export const createPackProgramInfoLoader = (handler: WebGLInferenceHandler, input: Tensor): ProgramInfoLoader =>
|
||||
({...packProgramMetadata, get: () => createPackProgramInfo(handler, input)});
|
||||
|
||||
/**
|
||||
* check output coordinate location and return false if it is outside input's width/height boundary
|
||||
*/
|
||||
function getOutOfBoundsCondition(rank: number, shape: readonly number[], dims: string[]): string {
|
||||
if (rank === 0) {
|
||||
return 'false';
|
||||
}
|
||||
if (rank === 1) {
|
||||
return `rc > ${shape[0]}`;
|
||||
}
|
||||
|
||||
let cond = '';
|
||||
for (let i = rank - 2; i < rank; i++) {
|
||||
cond += `${dims[i]} >= ${shape[i - rank + 2]}`;
|
||||
if (i < rank - 1) {
|
||||
cond += '||';
|
||||
}
|
||||
}
|
||||
|
||||
return cond;
|
||||
}
|
||||
|
||||
/**
|
||||
* code snippet to sample input texture with output coordiantes
|
||||
*/
|
||||
function getOutput(shape: readonly number[], dims: string[]): string {
|
||||
const rank = shape.length;
|
||||
|
||||
if (rank === 0) {
|
||||
return 'getA(), 0, 0, 0';
|
||||
}
|
||||
|
||||
if (rank === 1) {
|
||||
return `getA(rc),
|
||||
rc + 1 >= ${shape[0]} ? 0. : getA(rc + 1),
|
||||
0, 0`;
|
||||
}
|
||||
|
||||
const coord00 = 'r, c';
|
||||
const coord01 = 'r, cp1';
|
||||
const coord10 = 'rp1, c';
|
||||
const coord11 = 'rp1, cp1';
|
||||
let D = '';
|
||||
if (rank > 2) {
|
||||
for (let i = 0; i < rank - 2; ++i) {
|
||||
D = D + `${dims[i]},`;
|
||||
}
|
||||
}
|
||||
return `getA(${D}${coord00}),
|
||||
rEdge ? 0. : getA(${D}${coord10}),
|
||||
cEdge ? 0. : getA(${D}${coord01}),
|
||||
rEdge || cEdge ? 0. : getA(${D}${coord11})`;
|
||||
}
|
||||
|
||||
/**
|
||||
* code snippet to setup 4 coordinates and edge conditions
|
||||
*/
|
||||
function getSetup(rank: number, dims: string[], rows: number, cols: number): string {
|
||||
if (rank === 0 || rank === 1) {
|
||||
return '';
|
||||
}
|
||||
// rank >= 2 for width+height pack.
|
||||
else {
|
||||
const setup = `
|
||||
int r = ${dims[rank - 2]};
|
||||
int c = ${dims[rank - 1]};
|
||||
int rp1 = ${dims[rank - 2]} + 1;
|
||||
int cp1 = ${dims[rank - 1]} + 1;
|
||||
bool rEdge = rp1 >= ${cols};
|
||||
bool cEdge = cp1 >= ${rows};
|
||||
`;
|
||||
return setup;
|
||||
}
|
||||
}
|
||||
34
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/packing-utils.js
generated
vendored
Normal file
34
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/packing-utils.js
generated
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.unpackFromChannel = exports.getChannels = exports.getVecChannels = void 0;
|
||||
const utils_1 = require("../utils");
|
||||
function getVecChannels(name, rank) {
|
||||
return (0, utils_1.getGlChannels)(rank).map(d => `${name}.${d}`);
|
||||
}
|
||||
exports.getVecChannels = getVecChannels;
|
||||
function getChannels(name, rank) {
|
||||
if (rank === 1) {
|
||||
return [name];
|
||||
}
|
||||
return getVecChannels(name, rank);
|
||||
}
|
||||
exports.getChannels = getChannels;
|
||||
function unpackFromChannel() {
|
||||
return `
|
||||
float getChannel(vec4 frag, int dim) {
|
||||
int modCoord = imod(dim, 2);
|
||||
return modCoord == 0 ? frag.r : frag.g;
|
||||
}
|
||||
|
||||
float getChannel(vec4 frag, vec2 innerDims) {
|
||||
vec2 modCoord = mod(innerDims, 2.);
|
||||
return modCoord.x == 0. ?
|
||||
(modCoord.y == 0. ? frag.r : frag.g) :
|
||||
(modCoord.y == 0. ? frag.b : frag.a);
|
||||
}
|
||||
`;
|
||||
}
|
||||
exports.unpackFromChannel = unpackFromChannel;
|
||||
//# sourceMappingURL=packing-utils.js.map
|
||||
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/packing-utils.js.map
generated
vendored
Normal file
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/packing-utils.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"packing-utils.js","sourceRoot":"","sources":["packing-utils.ts"],"names":[],"mappings":";AAAA,4DAA4D;AAC5D,kCAAkC;;;AAElC,oCAAuC;AAEvC,SAAgB,cAAc,CAAC,IAAY,EAAE,IAAY;IACvD,OAAO,IAAA,qBAAa,EAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,IAAI,IAAI,CAAC,EAAE,CAAC,CAAC;AACtD,CAAC;AAFD,wCAEC;AAED,SAAgB,WAAW,CAAC,IAAY,EAAE,IAAY;IACpD,IAAI,IAAI,KAAK,CAAC,EAAE;QACd,OAAO,CAAC,IAAI,CAAC,CAAC;KACf;IACD,OAAO,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AACpC,CAAC;AALD,kCAKC;AAED,SAAgB,iBAAiB;IAC/B,OAAO;;;;;;;;;;;;GAYN,CAAC;AACJ,CAAC;AAdD,8CAcC"}
|
||||
31
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/packing-utils.ts
generated
vendored
Normal file
31
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/packing-utils.ts
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import {getGlChannels} from '../utils';
|
||||
|
||||
export function getVecChannels(name: string, rank: number): string[] {
|
||||
return getGlChannels(rank).map(d => `${name}.${d}`);
|
||||
}
|
||||
|
||||
export function getChannels(name: string, rank: number): string[] {
|
||||
if (rank === 1) {
|
||||
return [name];
|
||||
}
|
||||
return getVecChannels(name, rank);
|
||||
}
|
||||
|
||||
export function unpackFromChannel(): string {
|
||||
return `
|
||||
float getChannel(vec4 frag, int dim) {
|
||||
int modCoord = imod(dim, 2);
|
||||
return modCoord == 0 ? frag.r : frag.g;
|
||||
}
|
||||
|
||||
float getChannel(vec4 frag, vec2 innerDims) {
|
||||
vec2 modCoord = mod(innerDims, 2.);
|
||||
return modCoord.x == 0. ?
|
||||
(modCoord.y == 0. ? frag.r : frag.g) :
|
||||
(modCoord.y == 0. ? frag.b : frag.a);
|
||||
}
|
||||
`;
|
||||
}
|
||||
167
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/pad.js
generated
vendored
Normal file
167
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/pad.js
generated
vendored
Normal file
@@ -0,0 +1,167 @@
|
||||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.parsePadAttributesV11 = exports.padV11 = exports.parsePadAttributesV2 = exports.padV2 = void 0;
|
||||
const attribute_with_cache_key_1 = require("../../../attribute-with-cache-key");
|
||||
const util_1 = require("../../../util");
|
||||
const glsl_source_1 = require("../glsl-source");
|
||||
const types_1 = require("../types");
|
||||
const padProgramMetadata = {
|
||||
name: 'Pad',
|
||||
inputNames: ['A'],
|
||||
inputTypes: [types_1.TextureType.unpacked],
|
||||
};
|
||||
const padV2 = (inferenceHandler, inputs, attributes) => {
|
||||
validateInputsV2(inputs);
|
||||
const output = inferenceHandler.run(Object.assign(Object.assign({}, padProgramMetadata), { cacheHint: attributes.cacheKey, get: () => createPadProgramInfo(inferenceHandler, inputs[0], attributes) }), inputs);
|
||||
return [output];
|
||||
};
|
||||
exports.padV2 = padV2;
|
||||
const parsePadAttributesV2 = (node) => {
|
||||
const mode = node.attributes.getString('mode', 'constant');
|
||||
const value = node.attributes.getFloat('value', 0.0);
|
||||
const pads = node.attributes.getInts('pads');
|
||||
return (0, attribute_with_cache_key_1.createAttributeWithCacheKey)({ mode, value, pads });
|
||||
};
|
||||
exports.parsePadAttributesV2 = parsePadAttributesV2;
|
||||
const padV11 = (inferenceHandler, inputs, mode) => {
|
||||
validateInputsV11(inputs);
|
||||
const attrubutes = generatePadAttributesFromInputs(inferenceHandler, inputs, mode);
|
||||
return (0, exports.padV2)(inferenceHandler, [inputs[0]], attrubutes);
|
||||
};
|
||||
exports.padV11 = padV11;
|
||||
const parsePadAttributesV11 = (node) => node.attributes.getString('mode', 'constant');
|
||||
exports.parsePadAttributesV11 = parsePadAttributesV11;
|
||||
const generatePadAttributesFromInputs = (inferenceHandler, inputs, mode) => {
|
||||
if (!inferenceHandler.session.isInitializer(inputs[1].dataId) ||
|
||||
(inputs.length >= 3 && !inferenceHandler.session.isInitializer(inputs[2].dataId))) {
|
||||
throw new Error('dynamic pad attributes are not allowed');
|
||||
}
|
||||
const pads = Array.from(inputs[1].integerData);
|
||||
const value = (inputs.length >= 3) ? inputs[2].floatData[0] : 0.0;
|
||||
return (0, attribute_with_cache_key_1.createAttributeWithCacheKey)({ mode, pads, value });
|
||||
};
|
||||
const createPadProgramInfo = (inferenceHandler, input, attributes) => {
|
||||
const outputShape = util_1.ShapeUtil.padShape(input.dims.slice(), attributes.pads);
|
||||
const rank = outputShape.length;
|
||||
const padFunction = getPadFunction(inferenceHandler, input, attributes);
|
||||
const shaderSource = `
|
||||
${padFunction}
|
||||
float process(int[${rank}] indices) {
|
||||
return padA(indices);
|
||||
}`;
|
||||
return {
|
||||
name: 'Pad',
|
||||
inputNames: ['A'],
|
||||
inputTypes: [types_1.TextureType.unpacked],
|
||||
output: { dims: outputShape, type: input.type, textureType: types_1.TextureType.unpacked },
|
||||
shaderSource
|
||||
};
|
||||
};
|
||||
const validateInputsV2 = (inputs) => {
|
||||
if (!inputs || inputs.length !== 1) {
|
||||
throw new Error('Pad requires 1 input');
|
||||
}
|
||||
if (inputs[0].type !== 'float32' && inputs[0].type !== 'float64') {
|
||||
throw new Error('Invalid input type.');
|
||||
}
|
||||
};
|
||||
const validateInputsV11 = (inputs) => {
|
||||
if (!inputs || (inputs.length !== 2 && inputs.length !== 3)) {
|
||||
throw new Error('Pad requires 2 or 3 inputs');
|
||||
}
|
||||
if (inputs[1].type !== 'int32') {
|
||||
throw new Error('Invalid input type.');
|
||||
}
|
||||
if (inputs.length >= 3 && inputs[2].type === 'string') {
|
||||
throw new Error('Invalid input type.');
|
||||
}
|
||||
};
|
||||
const getPadFunction = (inferenceHandler, input, attributes) => {
|
||||
const glsl = (0, glsl_source_1.getGlsl)(inferenceHandler.session.backend.glContext.version);
|
||||
const [width, height] = inferenceHandler.calculateTextureWidthAndHeight(input.dims, types_1.TextureType.unpacked);
|
||||
const strides = util_1.ShapeUtil.computeStrides(input.dims);
|
||||
switch (attributes.mode) {
|
||||
case 'constant':
|
||||
return getPadConstant(glsl, input.dims, strides, width, height, attributes.pads, attributes.value);
|
||||
case 'reflect':
|
||||
return getPadReflect(glsl, input.dims, strides, width, height, attributes.pads);
|
||||
case 'edge':
|
||||
return getPadEdge(glsl, input.dims, strides, width, height, attributes.pads);
|
||||
default:
|
||||
throw new Error('Invalid mode');
|
||||
}
|
||||
};
|
||||
const getPadConstant = (glsl, shape, strides, width, height, pads, value) => {
|
||||
const rank = shape.length;
|
||||
let block = '';
|
||||
for (let i = rank - 1; i >= 0; --i) {
|
||||
block += `
|
||||
k = m[${i}] - ${pads[i]};
|
||||
if (k < 0) return constant;
|
||||
if (k >= ${shape[i]}) return constant;
|
||||
offset += k * ${strides[i]};
|
||||
`;
|
||||
}
|
||||
return `
|
||||
float padA(int m[${rank}]) {
|
||||
const float constant = float(${value});
|
||||
int offset = 0;
|
||||
int k = 0;
|
||||
${block}
|
||||
vec2 coords = offsetToCoords(offset, ${width}, ${height});
|
||||
float value = getColorAsFloat(${glsl.texture2D}(A, coords));
|
||||
return value;
|
||||
}
|
||||
`;
|
||||
};
|
||||
const getPadReflect = (glsl, shape, strides, width, height, pads) => {
|
||||
const rank = shape.length;
|
||||
let block = '';
|
||||
for (let i = rank - 1; i >= 0; --i) {
|
||||
block += `
|
||||
k = m[${i}] - ${pads[i]};
|
||||
if (k < 0) { k = -k; }
|
||||
{
|
||||
const int _2n_1 = ${2 * (shape[i] - 1)};
|
||||
k = int( mod( float(k), float(_2n_1) ) ) ;
|
||||
if(k >= ${shape[i]}) { k = _2n_1 - k; }
|
||||
}
|
||||
offset += k * ${strides[i]};
|
||||
`;
|
||||
}
|
||||
return `
|
||||
float padA(int m[${rank}]) {
|
||||
int offset = 0;
|
||||
int k = 0;
|
||||
${block}
|
||||
vec2 coords = offsetToCoords(offset, ${width}, ${height});
|
||||
float value = getColorAsFloat(${glsl.texture2D}(A, coords));
|
||||
return value;
|
||||
}
|
||||
`;
|
||||
};
|
||||
const getPadEdge = (glsl, shape, strides, width, height, pads) => {
|
||||
const rank = shape.length;
|
||||
let block = '';
|
||||
for (let i = rank - 1; i >= 0; --i) {
|
||||
block += `
|
||||
k = m[${i}] - ${pads[i]};
|
||||
if (k < 0) k = 0;
|
||||
if (k >= ${shape[i]}) k = ${shape[i] - 1};
|
||||
offset += k * ${strides[i]};
|
||||
`;
|
||||
}
|
||||
return `
|
||||
float padA(int m[${rank}]) {
|
||||
int offset = 0;
|
||||
int k = 0;
|
||||
${block}
|
||||
vec2 coords = offsetToCoords(offset, ${width}, ${height});
|
||||
float value = getColorAsFloat(${glsl.texture2D}(A, coords));
|
||||
return value;
|
||||
}
|
||||
`;
|
||||
};
|
||||
//# sourceMappingURL=pad.js.map
|
||||
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/pad.js.map
generated
vendored
Normal file
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/pad.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
205
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/pad.ts
generated
vendored
Normal file
205
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/pad.ts
generated
vendored
Normal file
@@ -0,0 +1,205 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../../../attribute-with-cache-key';
|
||||
import {Graph} from '../../../graph';
|
||||
import {OperatorImplementation, OperatorInitialization} from '../../../operators';
|
||||
import {Tensor} from '../../../tensor';
|
||||
import {ShapeUtil} from '../../../util';
|
||||
import {getGlsl, Glsl} from '../glsl-source';
|
||||
import {WebGLInferenceHandler} from '../inference-handler';
|
||||
import {ProgramInfo, TextureType} from '../types';
|
||||
|
||||
export interface PadAttributes extends AttributeWithCacheKey {
|
||||
readonly mode: string;
|
||||
readonly pads: number[];
|
||||
readonly value: number;
|
||||
}
|
||||
|
||||
const padProgramMetadata = {
|
||||
name: 'Pad',
|
||||
inputNames: ['A'],
|
||||
inputTypes: [TextureType.unpacked],
|
||||
};
|
||||
|
||||
export const padV2: OperatorImplementation<PadAttributes> =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: PadAttributes): Tensor[] => {
|
||||
validateInputsV2(inputs);
|
||||
const output = inferenceHandler.run(
|
||||
{
|
||||
...padProgramMetadata,
|
||||
cacheHint: attributes.cacheKey,
|
||||
get: () => createPadProgramInfo(inferenceHandler, inputs[0], attributes)
|
||||
},
|
||||
inputs);
|
||||
return [output];
|
||||
};
|
||||
|
||||
export const parsePadAttributesV2: OperatorInitialization<PadAttributes> = (node: Graph.Node): PadAttributes => {
|
||||
const mode = node.attributes.getString('mode', 'constant');
|
||||
const value = node.attributes.getFloat('value', 0.0);
|
||||
const pads = node.attributes.getInts('pads');
|
||||
return createAttributeWithCacheKey({mode, value, pads});
|
||||
};
|
||||
|
||||
export const padV11: OperatorImplementation<string> =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], mode: string): Tensor[] => {
|
||||
validateInputsV11(inputs);
|
||||
const attrubutes = generatePadAttributesFromInputs(inferenceHandler, inputs, mode);
|
||||
return padV2(inferenceHandler, [inputs[0]], attrubutes);
|
||||
};
|
||||
|
||||
export const parsePadAttributesV11: OperatorInitialization<string> = (node: Graph.Node): string =>
|
||||
node.attributes.getString('mode', 'constant');
|
||||
|
||||
const generatePadAttributesFromInputs =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], mode: string): PadAttributes => {
|
||||
if (!inferenceHandler.session.isInitializer(inputs[1].dataId) ||
|
||||
(inputs.length >= 3 && !inferenceHandler.session.isInitializer(inputs[2].dataId))) {
|
||||
throw new Error('dynamic pad attributes are not allowed');
|
||||
}
|
||||
|
||||
const pads = Array.from(inputs[1].integerData);
|
||||
const value = (inputs.length >= 3) ? inputs[2].floatData[0] : 0.0;
|
||||
|
||||
return createAttributeWithCacheKey({mode, pads, value});
|
||||
};
|
||||
|
||||
const createPadProgramInfo =
|
||||
(inferenceHandler: WebGLInferenceHandler, input: Tensor, attributes: PadAttributes): ProgramInfo => {
|
||||
const outputShape = ShapeUtil.padShape(input.dims.slice(), attributes.pads);
|
||||
const rank = outputShape.length;
|
||||
const padFunction = getPadFunction(inferenceHandler, input, attributes);
|
||||
const shaderSource = `
|
||||
${padFunction}
|
||||
float process(int[${rank}] indices) {
|
||||
return padA(indices);
|
||||
}`;
|
||||
return {
|
||||
name: 'Pad',
|
||||
inputNames: ['A'],
|
||||
inputTypes: [TextureType.unpacked],
|
||||
output: {dims: outputShape, type: input.type, textureType: TextureType.unpacked},
|
||||
shaderSource
|
||||
};
|
||||
};
|
||||
|
||||
const validateInputsV2 = (inputs: Tensor[]): void => {
|
||||
if (!inputs || inputs.length !== 1) {
|
||||
throw new Error('Pad requires 1 input');
|
||||
}
|
||||
if (inputs[0].type !== 'float32' && inputs[0].type !== 'float64') {
|
||||
throw new Error('Invalid input type.');
|
||||
}
|
||||
};
|
||||
|
||||
const validateInputsV11 = (inputs: Tensor[]): void => {
|
||||
if (!inputs || (inputs.length !== 2 && inputs.length !== 3)) {
|
||||
throw new Error('Pad requires 2 or 3 inputs');
|
||||
}
|
||||
if (inputs[1].type !== 'int32') {
|
||||
throw new Error('Invalid input type.');
|
||||
}
|
||||
if (inputs.length >= 3 && inputs[2].type === 'string') {
|
||||
throw new Error('Invalid input type.');
|
||||
}
|
||||
};
|
||||
|
||||
const getPadFunction = (inferenceHandler: WebGLInferenceHandler, input: Tensor, attributes: PadAttributes): string => {
|
||||
const glsl = getGlsl(inferenceHandler.session.backend.glContext.version);
|
||||
const [width, height] = inferenceHandler.calculateTextureWidthAndHeight(input.dims, TextureType.unpacked);
|
||||
const strides = ShapeUtil.computeStrides(input.dims);
|
||||
|
||||
switch (attributes.mode) {
|
||||
case 'constant':
|
||||
return getPadConstant(glsl, input.dims, strides, width, height, attributes.pads, attributes.value);
|
||||
case 'reflect':
|
||||
return getPadReflect(glsl, input.dims, strides, width, height, attributes.pads);
|
||||
case 'edge':
|
||||
return getPadEdge(glsl, input.dims, strides, width, height, attributes.pads);
|
||||
default:
|
||||
throw new Error('Invalid mode');
|
||||
}
|
||||
};
|
||||
|
||||
const getPadConstant =
|
||||
(glsl: Glsl, shape: readonly number[], strides: readonly number[], width: number, height: number, pads: number[],
|
||||
value: number): string => {
|
||||
const rank = shape.length;
|
||||
let block = '';
|
||||
for (let i = rank - 1; i >= 0; --i) {
|
||||
block += `
|
||||
k = m[${i}] - ${pads[i]};
|
||||
if (k < 0) return constant;
|
||||
if (k >= ${shape[i]}) return constant;
|
||||
offset += k * ${strides[i]};
|
||||
`;
|
||||
}
|
||||
return `
|
||||
float padA(int m[${rank}]) {
|
||||
const float constant = float(${value});
|
||||
int offset = 0;
|
||||
int k = 0;
|
||||
${block}
|
||||
vec2 coords = offsetToCoords(offset, ${width}, ${height});
|
||||
float value = getColorAsFloat(${glsl.texture2D}(A, coords));
|
||||
return value;
|
||||
}
|
||||
`;
|
||||
};
|
||||
|
||||
const getPadReflect =
|
||||
(glsl: Glsl, shape: readonly number[], strides: readonly number[], width: number, height: number, pads: number[]):
|
||||
string => {
|
||||
const rank = shape.length;
|
||||
|
||||
let block = '';
|
||||
for (let i = rank - 1; i >= 0; --i) {
|
||||
block += `
|
||||
k = m[${i}] - ${pads[i]};
|
||||
if (k < 0) { k = -k; }
|
||||
{
|
||||
const int _2n_1 = ${2 * (shape[i] - 1)};
|
||||
k = int( mod( float(k), float(_2n_1) ) ) ;
|
||||
if(k >= ${shape[i]}) { k = _2n_1 - k; }
|
||||
}
|
||||
offset += k * ${strides[i]};
|
||||
`;
|
||||
}
|
||||
return `
|
||||
float padA(int m[${rank}]) {
|
||||
int offset = 0;
|
||||
int k = 0;
|
||||
${block}
|
||||
vec2 coords = offsetToCoords(offset, ${width}, ${height});
|
||||
float value = getColorAsFloat(${glsl.texture2D}(A, coords));
|
||||
return value;
|
||||
}
|
||||
`;
|
||||
};
|
||||
|
||||
const getPadEdge =
|
||||
(glsl: Glsl, shape: readonly number[], strides: readonly number[], width: number, height: number, pads: number[]):
|
||||
string => {
|
||||
const rank = shape.length;
|
||||
|
||||
let block = '';
|
||||
for (let i = rank - 1; i >= 0; --i) {
|
||||
block += `
|
||||
k = m[${i}] - ${pads[i]};
|
||||
if (k < 0) k = 0;
|
||||
if (k >= ${shape[i]}) k = ${shape[i] - 1};
|
||||
offset += k * ${strides[i]};
|
||||
`;
|
||||
}
|
||||
return `
|
||||
float padA(int m[${rank}]) {
|
||||
int offset = 0;
|
||||
int k = 0;
|
||||
${block}
|
||||
vec2 coords = offsetToCoords(offset, ${width}, ${height});
|
||||
float value = getColorAsFloat(${glsl.texture2D}(A, coords));
|
||||
return value;
|
||||
}
|
||||
`;
|
||||
};
|
||||
304
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/pool.js
generated
vendored
Normal file
304
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/pool.js
generated
vendored
Normal file
@@ -0,0 +1,304 @@
|
||||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.globalMaxPool = exports.parseMaxPoolAttributes = exports.maxPool = exports.parseGlobalAveragePoolAttributes = exports.globalAveragePool = exports.parseAveragePoolAttributes = exports.averagePool = void 0;
|
||||
const attribute_with_cache_key_1 = require("../../../attribute-with-cache-key");
|
||||
const util_1 = require("../../../util");
|
||||
const types_1 = require("../types");
|
||||
const averagePool = (inferenceHandler, inputs, attributes) => {
|
||||
validateInputs(inputs);
|
||||
const metadata = { name: 'AveragePool', inputNames: ['X'], inputTypes: [types_1.TextureType.unpacked], cacheHint: attributes.cacheKey };
|
||||
const output = inferenceHandler.run(Object.assign(Object.assign({}, metadata), { get: () => createAveragePoolProgramInfo(inputs, metadata, false, attributes) }), inputs);
|
||||
return [output];
|
||||
};
|
||||
exports.averagePool = averagePool;
|
||||
const parseAveragePoolAttributes = (node) => {
|
||||
const autoPad = node.attributes.getString('auto_pad', 'NOTSET');
|
||||
const ceilMode = node.attributes.getInt('ceil_mode', 0);
|
||||
const countIncludePad = (node.attributes.getInt('count_include_pad', 0) === 0 ? false : true);
|
||||
const kernelShape = node.attributes.getInts('kernel_shape');
|
||||
const strides = node.attributes.getInts('strides', []);
|
||||
const pads = node.attributes.getInts('pads', []);
|
||||
// TODO: support attribute 'ceil_mode'
|
||||
if (ceilMode !== 0) {
|
||||
throw new Error('using ceil() in shape computation is not yet supported for AveragePool');
|
||||
}
|
||||
return (0, attribute_with_cache_key_1.createAttributeWithCacheKey)({ autoPad, ceilMode, countIncludePad, kernelShape, strides, pads });
|
||||
};
|
||||
exports.parseAveragePoolAttributes = parseAveragePoolAttributes;
|
||||
const createAveragePoolProgramInfo = (inputs, metadata, isGlobalOperator, attributes) => {
|
||||
const [adjustedAttributes, outputShape] = getAdjustedPoolAttributesAndOutputShape(inputs, attributes, isGlobalOperator);
|
||||
const kernelSize = util_1.ShapeUtil.size(adjustedAttributes.kernelShape);
|
||||
const op1 = 'value += _X(x);';
|
||||
let op2 = '';
|
||||
if (adjustedAttributes.countIncludePad) {
|
||||
op2 += `value /= float(${kernelSize});`;
|
||||
}
|
||||
else {
|
||||
op2 += `value /= float(${kernelSize} - pad);`;
|
||||
}
|
||||
const poolingCode = generatePoolingCode(inputs[0].dims, adjustedAttributes, op1, op2, '0.0');
|
||||
const shaderSource = `
|
||||
${poolingCode}
|
||||
`;
|
||||
return Object.assign(Object.assign({}, metadata), { output: { dims: outputShape, type: inputs[0].type, textureType: types_1.TextureType.unpacked }, shaderSource });
|
||||
};
|
||||
const globalAveragePool = (inferenceHandler, inputs, attributes) => {
|
||||
validateInputs(inputs);
|
||||
const metadata = {
|
||||
name: 'GlobalAveragePool',
|
||||
inputNames: ['X'],
|
||||
inputTypes: [types_1.TextureType.unpacked],
|
||||
cacheHint: `${attributes.countIncludePad}`
|
||||
};
|
||||
const output = inferenceHandler.run(Object.assign(Object.assign({}, metadata), { get: () => createAveragePoolProgramInfo(inputs, metadata, true, attributes) }), inputs);
|
||||
return [output];
|
||||
};
|
||||
exports.globalAveragePool = globalAveragePool;
|
||||
const parseGlobalAveragePoolAttributes = (node) => {
|
||||
const countIncludePad = (node.attributes.getInt('count_include_pad', 0) === 0 ? false : true);
|
||||
return (0, attribute_with_cache_key_1.createAttributeWithCacheKey)({ autoPad: '', ceilMode: 0, countIncludePad, kernelShape: [], strides: [], pads: [] });
|
||||
};
|
||||
exports.parseGlobalAveragePoolAttributes = parseGlobalAveragePoolAttributes;
|
||||
const maxPool = (inferenceHandler, inputs, attributes) => {
|
||||
validateInputs(inputs);
|
||||
const metadata = { name: 'MaxPool', inputNames: ['X'], inputTypes: [types_1.TextureType.unpacked], cacheHint: attributes.cacheKey };
|
||||
const output = inferenceHandler.run(Object.assign(Object.assign({}, metadata), { get: () => createMaxPoolProgramInfo(inputs, metadata, false, attributes) }), inputs);
|
||||
return [output];
|
||||
};
|
||||
exports.maxPool = maxPool;
|
||||
const parseMaxPoolAttributes = (node) => {
|
||||
const autoPad = node.attributes.getString('auto_pad', 'NOTSET');
|
||||
const ceilMode = node.attributes.getInt('ceil_mode', 0);
|
||||
const kernelShape = node.attributes.getInts('kernel_shape');
|
||||
const strides = node.attributes.getInts('strides', []);
|
||||
const pads = node.attributes.getInts('pads', []);
|
||||
const storageOrder = node.attributes.getInt('storage_order', 0);
|
||||
const dilations = node.attributes.getInts('dilations', []);
|
||||
// TODO: support attribute 'ceil_mode' and 'storage_order'
|
||||
if (storageOrder !== 0) {
|
||||
throw new Error('column major storage order is not yet supported for MaxPool');
|
||||
}
|
||||
if (ceilMode !== 0) {
|
||||
throw new Error('using ceil() in shape computation is not yet supported for MaxPool');
|
||||
}
|
||||
return (0, attribute_with_cache_key_1.createAttributeWithCacheKey)({ autoPad, ceilMode, countIncludePad: false, kernelShape, strides, pads, storageOrder, dilations });
|
||||
};
|
||||
exports.parseMaxPoolAttributes = parseMaxPoolAttributes;
|
||||
const createMaxPoolProgramInfo = (inputs, metadata, isGlobalOperator, attributes) => {
|
||||
const [adjustedAttributes, outputShape] = getAdjustedPoolAttributesAndOutputShape(inputs, attributes, isGlobalOperator);
|
||||
const op1 = `
|
||||
value = max(_X(x), value);
|
||||
`;
|
||||
const op2 = '';
|
||||
const poolingCode = generatePoolingCode(inputs[0].dims, adjustedAttributes, op1, op2, '-1e5');
|
||||
const shaderSource = `
|
||||
${poolingCode}
|
||||
`;
|
||||
return Object.assign(Object.assign({}, metadata), { output: { dims: outputShape, type: inputs[0].type, textureType: types_1.TextureType.unpacked }, shaderSource });
|
||||
};
|
||||
const getAdjustedPoolAttributesAndOutputShape = (inputs, attributes, isGlobalOperator) => {
|
||||
const inputShape = inputs[0].dims.slice();
|
||||
const hasDilations = Object.hasOwnProperty.call(attributes, 'dilations');
|
||||
const kernelShape = attributes.kernelShape.slice();
|
||||
const strides = attributes.strides.slice();
|
||||
const dilations = hasDilations ? attributes.dilations.slice() : [];
|
||||
const pads = attributes.pads.slice();
|
||||
util_1.PoolConvUtil.adjustPoolAttributes(isGlobalOperator, inputShape, kernelShape, strides, dilations, pads);
|
||||
const outputShape = util_1.PoolConvUtil.computePoolOutputShape(isGlobalOperator, inputShape, strides, dilations, kernelShape, pads, attributes.autoPad);
|
||||
const newAttributes = Object.assign({}, attributes);
|
||||
if (hasDilations) {
|
||||
Object.assign(newAttributes, { kernelShape, strides, pads, dilations, cacheKey: attributes.cacheKey });
|
||||
}
|
||||
else {
|
||||
Object.assign(newAttributes, { kernelShape, strides, pads, cacheKey: attributes.cacheKey });
|
||||
}
|
||||
return [newAttributes, outputShape];
|
||||
};
|
||||
const globalMaxPoolAttributes = {
|
||||
autoPad: '',
|
||||
ceilMode: 0,
|
||||
countIncludePad: false,
|
||||
kernelShape: [],
|
||||
strides: [],
|
||||
pads: [],
|
||||
storageOrder: 0,
|
||||
dilations: [],
|
||||
cacheKey: ''
|
||||
};
|
||||
const globalMaxPoolMetadata = {
|
||||
name: 'GlobalMaxPool',
|
||||
inputNames: ['X'],
|
||||
inputTypes: [types_1.TextureType.unpacked]
|
||||
};
|
||||
const globalMaxPool = (inferenceHandler, inputs) => {
|
||||
validateInputs(inputs);
|
||||
const output = inferenceHandler.run(Object.assign(Object.assign({}, globalMaxPoolMetadata), { get: () => createMaxPoolProgramInfo(inputs, globalMaxPoolMetadata, true, globalMaxPoolAttributes) }), inputs);
|
||||
return [output];
|
||||
};
|
||||
exports.globalMaxPool = globalMaxPool;
|
||||
const validateInputs = (inputs) => {
|
||||
if (!inputs || inputs.length !== 1) {
|
||||
throw new Error('Pool ops requires 1 input.');
|
||||
}
|
||||
if (inputs[0].type !== 'float32' && inputs[0].type !== 'float64') {
|
||||
throw new Error('Invalid input type.');
|
||||
}
|
||||
};
|
||||
const generatePoolingCode = (inputDims, attributes, op1, op2, start) => {
|
||||
const rank = inputDims.length;
|
||||
if (attributes.kernelShape.length <= 2) {
|
||||
const kw = attributes.kernelShape[attributes.kernelShape.length - 1];
|
||||
const sw = attributes.strides[attributes.strides.length - 1];
|
||||
const pwStart = attributes.pads[attributes.pads.length / 2 - 1];
|
||||
const pwEnd = attributes.pads[attributes.pads.length - 1];
|
||||
const dimW = inputDims[rank - 1];
|
||||
let codeW = '';
|
||||
let codeH = '';
|
||||
let codeHEnd = '';
|
||||
if (pwStart + pwEnd !== 0) {
|
||||
codeW = `
|
||||
for (int i = 0; i < ${kw}; i++) {
|
||||
x[${rank} - 1] = indices[${rank} - 1] * ${sw} - ${pwStart} + i;
|
||||
if (x[${rank} - 1] < 0 || x[${rank} - 1] >= ${dimW}) {
|
||||
pad++;
|
||||
continue;
|
||||
}
|
||||
${op1}
|
||||
}`;
|
||||
}
|
||||
else {
|
||||
codeW = `
|
||||
for (int i = 0; i < ${kw}; i++) {
|
||||
x[${rank} - 1] = indices[${rank} - 1] * ${sw} - ${pwStart} + i;
|
||||
${op1}
|
||||
}`;
|
||||
}
|
||||
if (attributes.kernelShape.length === 2) {
|
||||
const kh = attributes.kernelShape[attributes.kernelShape.length - 2];
|
||||
const sh = attributes.strides[attributes.strides.length - 2];
|
||||
const phStart = attributes.pads[attributes.pads.length / 2 - 2];
|
||||
const phEnd = attributes.pads[attributes.pads.length - 2];
|
||||
const dimH = inputDims[rank - 2];
|
||||
if (phStart + phEnd !== 0) {
|
||||
codeH = `
|
||||
for (int j = 0; j < ${kh}; j++) {
|
||||
x[${rank} - 2] = indices[${rank} - 2] * ${sh} - ${phStart} + j;
|
||||
if (x[${rank} - 2] < 0 || x[${rank} - 2] >= ${dimH}) {
|
||||
pad+= ${kw};
|
||||
continue;
|
||||
}
|
||||
`;
|
||||
}
|
||||
else {
|
||||
codeH = `
|
||||
for (int j = 0; j < ${kh}; j++) {
|
||||
x[${rank} - 2] = indices[${rank} - 2] * ${sh} - ${phStart} + j;
|
||||
`;
|
||||
}
|
||||
codeHEnd = `
|
||||
}
|
||||
`;
|
||||
}
|
||||
const poolingCode = `
|
||||
float process(int indices[${rank}]) {
|
||||
int x[${rank}];
|
||||
copyVec(indices, x);
|
||||
|
||||
float value = ${start};
|
||||
int pad = 0;
|
||||
${codeH}
|
||||
${codeW}
|
||||
${codeHEnd}
|
||||
${op2}
|
||||
return value;
|
||||
}
|
||||
`;
|
||||
return poolingCode;
|
||||
}
|
||||
else {
|
||||
const kernelSize = util_1.ShapeUtil.size(attributes.kernelShape);
|
||||
const kernelStrides = util_1.ShapeUtil.computeStrides(attributes.kernelShape);
|
||||
const stridesRank = kernelStrides.length;
|
||||
const padsRank = attributes.pads.length;
|
||||
const offsetToIndicesFunction = offsetToIndices(stridesRank);
|
||||
const copyInputDims = copyArray(inputDims, 'inputDims');
|
||||
const copyPads = copyArray(attributes.pads, 'pads');
|
||||
const copyKernelStrides = copyArray(kernelStrides, 'kernelStrides');
|
||||
const copyStrides = copyArray(attributes.strides, 'strides');
|
||||
const hasPads = attributes.pads.reduce((sum, cur) => sum + cur);
|
||||
let padCode = '';
|
||||
if (hasPads) {
|
||||
padCode = `
|
||||
if (x[j] >= inputDims[j] || x[j] < 0) {
|
||||
pad++;
|
||||
isPad = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!isPad) {
|
||||
${op1}
|
||||
}`;
|
||||
}
|
||||
else {
|
||||
padCode = `
|
||||
}
|
||||
${op1}
|
||||
`;
|
||||
}
|
||||
const poolingCode = `
|
||||
${offsetToIndicesFunction}
|
||||
float process(int indices[${rank}]) {
|
||||
int x[${rank}];
|
||||
copyVec(indices, x);
|
||||
int offset[${stridesRank}];
|
||||
int pads[${padsRank}];
|
||||
int inputDims[${rank}];
|
||||
int kernelStrides[${stridesRank}];
|
||||
int strides[${stridesRank}];
|
||||
${copyPads}
|
||||
${copyInputDims}
|
||||
${copyStrides}
|
||||
${copyKernelStrides}
|
||||
|
||||
float value = ${start};
|
||||
int pad = 0;
|
||||
bool isPad = false;
|
||||
for (int i = 0; i < ${kernelSize}; i++) {
|
||||
offsetToIndices(i, kernelStrides, offset);
|
||||
isPad = false;
|
||||
for (int j = ${rank} - ${stridesRank}; j < ${rank}; j++) {
|
||||
x[j] = indices[j] * strides[j - ${rank} + ${stridesRank}]
|
||||
+ offset[j - ${rank} + ${stridesRank}] - pads[j - 2];
|
||||
${padCode}
|
||||
}
|
||||
${op2}
|
||||
|
||||
return value;
|
||||
}
|
||||
`;
|
||||
return poolingCode;
|
||||
}
|
||||
};
|
||||
const copyArray = (array, arrayName) => {
|
||||
let block = '';
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
block += `
|
||||
${arrayName}[${i}] = ${array[i]};
|
||||
`;
|
||||
}
|
||||
return block;
|
||||
};
|
||||
const offsetToIndices = (rank) => `
|
||||
void offsetToIndices(int offset, int[${rank}] strides, out int[${rank}] indices) {
|
||||
if (${rank} == 0) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < ${rank} - 1; ++i) {
|
||||
indices[i] = offset / strides[i];
|
||||
offset -= indices[i] * strides[i];
|
||||
}
|
||||
indices[${rank} - 1] = offset;
|
||||
}`;
|
||||
//# sourceMappingURL=pool.js.map
|
||||
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/pool.js.map
generated
vendored
Normal file
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/pool.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
367
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/pool.ts
generated
vendored
Normal file
367
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/pool.ts
generated
vendored
Normal file
@@ -0,0 +1,367 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../../../attribute-with-cache-key';
|
||||
import {Graph} from '../../../graph';
|
||||
import {OperatorImplementation, OperatorInitialization} from '../../../operators';
|
||||
import {Tensor} from '../../../tensor';
|
||||
import {PoolConvUtil, ShapeUtil} from '../../../util';
|
||||
import {WebGLInferenceHandler} from '../inference-handler';
|
||||
import {ProgramInfo, ProgramMetadata, TextureType} from '../types';
|
||||
|
||||
export interface AveragePoolAttributes extends AttributeWithCacheKey {
|
||||
readonly autoPad: string;
|
||||
readonly ceilMode: number;
|
||||
readonly countIncludePad: boolean;
|
||||
readonly kernelShape: readonly number[];
|
||||
readonly strides: readonly number[];
|
||||
readonly pads: readonly number[];
|
||||
}
|
||||
|
||||
export const averagePool: OperatorImplementation<AveragePoolAttributes> =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: AveragePoolAttributes): Tensor[] => {
|
||||
validateInputs(inputs);
|
||||
const metadata =
|
||||
{name: 'AveragePool', inputNames: ['X'], inputTypes: [TextureType.unpacked], cacheHint: attributes.cacheKey};
|
||||
const output = inferenceHandler.run(
|
||||
{...metadata, get: () => createAveragePoolProgramInfo(inputs, metadata, false, attributes)}, inputs);
|
||||
return [output];
|
||||
};
|
||||
|
||||
export const parseAveragePoolAttributes: OperatorInitialization<AveragePoolAttributes> =
|
||||
(node: Graph.Node): AveragePoolAttributes => {
|
||||
const autoPad = node.attributes.getString('auto_pad', 'NOTSET');
|
||||
const ceilMode = node.attributes.getInt('ceil_mode', 0);
|
||||
const countIncludePad = (node.attributes.getInt('count_include_pad', 0) === 0 ? false : true);
|
||||
const kernelShape = node.attributes.getInts('kernel_shape');
|
||||
const strides = node.attributes.getInts('strides', []);
|
||||
const pads = node.attributes.getInts('pads', []);
|
||||
|
||||
// TODO: support attribute 'ceil_mode'
|
||||
if (ceilMode !== 0) {
|
||||
throw new Error('using ceil() in shape computation is not yet supported for AveragePool');
|
||||
}
|
||||
|
||||
return createAttributeWithCacheKey({autoPad, ceilMode, countIncludePad, kernelShape, strides, pads});
|
||||
};
|
||||
|
||||
const createAveragePoolProgramInfo =
|
||||
(inputs: Tensor[], metadata: ProgramMetadata, isGlobalOperator: boolean, attributes: AveragePoolAttributes):
|
||||
ProgramInfo => {
|
||||
const [adjustedAttributes, outputShape] =
|
||||
getAdjustedPoolAttributesAndOutputShape(inputs, attributes, isGlobalOperator);
|
||||
const kernelSize = ShapeUtil.size(adjustedAttributes.kernelShape);
|
||||
const op1 = 'value += _X(x);';
|
||||
let op2 = '';
|
||||
if (adjustedAttributes.countIncludePad) {
|
||||
op2 += `value /= float(${kernelSize});`;
|
||||
} else {
|
||||
op2 += `value /= float(${kernelSize} - pad);`;
|
||||
}
|
||||
const poolingCode = generatePoolingCode(inputs[0].dims, adjustedAttributes, op1, op2, '0.0');
|
||||
const shaderSource = `
|
||||
${poolingCode}
|
||||
`;
|
||||
return {
|
||||
...metadata,
|
||||
output: {dims: outputShape, type: inputs[0].type, textureType: TextureType.unpacked},
|
||||
shaderSource
|
||||
};
|
||||
};
|
||||
|
||||
export const globalAveragePool: OperatorImplementation<AveragePoolAttributes> =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: AveragePoolAttributes): Tensor[] => {
|
||||
validateInputs(inputs);
|
||||
const metadata = {
|
||||
name: 'GlobalAveragePool',
|
||||
inputNames: ['X'],
|
||||
inputTypes: [TextureType.unpacked],
|
||||
cacheHint: `${attributes.countIncludePad}`
|
||||
};
|
||||
const output = inferenceHandler.run(
|
||||
{...metadata, get: () => createAveragePoolProgramInfo(inputs, metadata, true, attributes)}, inputs);
|
||||
return [output];
|
||||
};
|
||||
|
||||
export const parseGlobalAveragePoolAttributes: OperatorInitialization<AveragePoolAttributes> =
|
||||
(node: Graph.Node): AveragePoolAttributes => {
|
||||
const countIncludePad = (node.attributes.getInt('count_include_pad', 0) === 0 ? false : true);
|
||||
return createAttributeWithCacheKey(
|
||||
{autoPad: '', ceilMode: 0, countIncludePad, kernelShape: [], strides: [], pads: []});
|
||||
};
|
||||
|
||||
export interface MaxPoolAttributes extends AveragePoolAttributes {
|
||||
readonly storageOrder: number;
|
||||
readonly dilations: number[];
|
||||
}
|
||||
|
||||
export const maxPool: OperatorImplementation<MaxPoolAttributes> =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: MaxPoolAttributes): Tensor[] => {
|
||||
validateInputs(inputs);
|
||||
const metadata =
|
||||
{name: 'MaxPool', inputNames: ['X'], inputTypes: [TextureType.unpacked], cacheHint: attributes.cacheKey};
|
||||
const output = inferenceHandler.run(
|
||||
{...metadata, get: () => createMaxPoolProgramInfo(inputs, metadata, false, attributes)}, inputs);
|
||||
return [output];
|
||||
};
|
||||
|
||||
export const parseMaxPoolAttributes: OperatorInitialization<MaxPoolAttributes> =
|
||||
(node: Graph.Node): MaxPoolAttributes => {
|
||||
const autoPad = node.attributes.getString('auto_pad', 'NOTSET');
|
||||
const ceilMode = node.attributes.getInt('ceil_mode', 0);
|
||||
const kernelShape = node.attributes.getInts('kernel_shape');
|
||||
const strides = node.attributes.getInts('strides', []);
|
||||
const pads = node.attributes.getInts('pads', []);
|
||||
const storageOrder = node.attributes.getInt('storage_order', 0);
|
||||
const dilations = node.attributes.getInts('dilations', []);
|
||||
|
||||
// TODO: support attribute 'ceil_mode' and 'storage_order'
|
||||
if (storageOrder !== 0) {
|
||||
throw new Error('column major storage order is not yet supported for MaxPool');
|
||||
}
|
||||
if (ceilMode !== 0) {
|
||||
throw new Error('using ceil() in shape computation is not yet supported for MaxPool');
|
||||
}
|
||||
|
||||
return createAttributeWithCacheKey(
|
||||
{autoPad, ceilMode, countIncludePad: false, kernelShape, strides, pads, storageOrder, dilations});
|
||||
};
|
||||
|
||||
const createMaxPoolProgramInfo =
|
||||
(inputs: Tensor[], metadata: ProgramMetadata, isGlobalOperator: boolean, attributes: MaxPoolAttributes):
|
||||
ProgramInfo => {
|
||||
const [adjustedAttributes, outputShape] =
|
||||
getAdjustedPoolAttributesAndOutputShape(inputs, attributes, isGlobalOperator);
|
||||
const op1 = `
|
||||
value = max(_X(x), value);
|
||||
`;
|
||||
const op2 = '';
|
||||
const poolingCode = generatePoolingCode(inputs[0].dims, adjustedAttributes, op1, op2, '-1e5');
|
||||
const shaderSource = `
|
||||
${poolingCode}
|
||||
`;
|
||||
return {
|
||||
...metadata,
|
||||
output: {dims: outputShape, type: inputs[0].type, textureType: TextureType.unpacked},
|
||||
shaderSource
|
||||
};
|
||||
};
|
||||
|
||||
const getAdjustedPoolAttributesAndOutputShape =
|
||||
(inputs: Tensor[], attributes: AveragePoolAttributes|MaxPoolAttributes, isGlobalOperator: boolean):
|
||||
[AveragePoolAttributes|MaxPoolAttributes, number[]] => {
|
||||
const inputShape = inputs[0].dims.slice();
|
||||
const hasDilations = Object.hasOwnProperty.call(attributes, 'dilations');
|
||||
const kernelShape = attributes.kernelShape.slice();
|
||||
const strides = attributes.strides.slice();
|
||||
const dilations: number[] = hasDilations ? (attributes as MaxPoolAttributes).dilations.slice() : [];
|
||||
const pads = attributes.pads.slice();
|
||||
PoolConvUtil.adjustPoolAttributes(isGlobalOperator, inputShape, kernelShape, strides, dilations, pads);
|
||||
|
||||
const outputShape = PoolConvUtil.computePoolOutputShape(
|
||||
isGlobalOperator, inputShape, strides, dilations, kernelShape, pads, attributes.autoPad);
|
||||
|
||||
const newAttributes = Object.assign({}, attributes);
|
||||
if (hasDilations) {
|
||||
Object.assign(newAttributes, {kernelShape, strides, pads, dilations, cacheKey: attributes.cacheKey});
|
||||
} else {
|
||||
Object.assign(newAttributes, {kernelShape, strides, pads, cacheKey: attributes.cacheKey});
|
||||
}
|
||||
return [newAttributes, outputShape];
|
||||
};
|
||||
|
||||
const globalMaxPoolAttributes = {
|
||||
autoPad: '',
|
||||
ceilMode: 0,
|
||||
countIncludePad: false,
|
||||
kernelShape: [],
|
||||
strides: [],
|
||||
pads: [],
|
||||
storageOrder: 0,
|
||||
dilations: [],
|
||||
cacheKey: ''
|
||||
};
|
||||
|
||||
const globalMaxPoolMetadata = {
|
||||
name: 'GlobalMaxPool',
|
||||
inputNames: ['X'],
|
||||
inputTypes: [TextureType.unpacked]
|
||||
};
|
||||
|
||||
export const globalMaxPool = (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[]): Tensor[] => {
|
||||
validateInputs(inputs);
|
||||
const output = inferenceHandler.run(
|
||||
{
|
||||
...globalMaxPoolMetadata,
|
||||
get: () => createMaxPoolProgramInfo(inputs, globalMaxPoolMetadata, true, globalMaxPoolAttributes)
|
||||
},
|
||||
inputs);
|
||||
return [output];
|
||||
};
|
||||
|
||||
const validateInputs = (inputs: Tensor[]): void => {
|
||||
if (!inputs || inputs.length !== 1) {
|
||||
throw new Error('Pool ops requires 1 input.');
|
||||
}
|
||||
if (inputs[0].type !== 'float32' && inputs[0].type !== 'float64') {
|
||||
throw new Error('Invalid input type.');
|
||||
}
|
||||
};
|
||||
|
||||
const generatePoolingCode =
|
||||
(inputDims: readonly number[], attributes: AveragePoolAttributes, op1: string, op2: string, start: string):
|
||||
string => {
|
||||
const rank = inputDims.length;
|
||||
if (attributes.kernelShape.length <= 2) {
|
||||
const kw = attributes.kernelShape[attributes.kernelShape.length - 1];
|
||||
const sw = attributes.strides[attributes.strides.length - 1];
|
||||
const pwStart = attributes.pads[attributes.pads.length / 2 - 1];
|
||||
const pwEnd = attributes.pads[attributes.pads.length - 1];
|
||||
const dimW = inputDims[rank - 1];
|
||||
let codeW = '';
|
||||
let codeH = '';
|
||||
let codeHEnd = '';
|
||||
if (pwStart + pwEnd !== 0) {
|
||||
codeW = `
|
||||
for (int i = 0; i < ${kw}; i++) {
|
||||
x[${rank} - 1] = indices[${rank} - 1] * ${sw} - ${pwStart} + i;
|
||||
if (x[${rank} - 1] < 0 || x[${rank} - 1] >= ${dimW}) {
|
||||
pad++;
|
||||
continue;
|
||||
}
|
||||
${op1}
|
||||
}`;
|
||||
} else {
|
||||
codeW = `
|
||||
for (int i = 0; i < ${kw}; i++) {
|
||||
x[${rank} - 1] = indices[${rank} - 1] * ${sw} - ${pwStart} + i;
|
||||
${op1}
|
||||
}`;
|
||||
}
|
||||
|
||||
if (attributes.kernelShape.length === 2) {
|
||||
const kh = attributes.kernelShape[attributes.kernelShape.length - 2];
|
||||
const sh = attributes.strides[attributes.strides.length - 2];
|
||||
const phStart = attributes.pads[attributes.pads.length / 2 - 2];
|
||||
const phEnd = attributes.pads[attributes.pads.length - 2];
|
||||
const dimH = inputDims[rank - 2];
|
||||
if (phStart + phEnd !== 0) {
|
||||
codeH = `
|
||||
for (int j = 0; j < ${kh}; j++) {
|
||||
x[${rank} - 2] = indices[${rank} - 2] * ${sh} - ${phStart} + j;
|
||||
if (x[${rank} - 2] < 0 || x[${rank} - 2] >= ${dimH}) {
|
||||
pad+= ${kw};
|
||||
continue;
|
||||
}
|
||||
`;
|
||||
} else {
|
||||
codeH = `
|
||||
for (int j = 0; j < ${kh}; j++) {
|
||||
x[${rank} - 2] = indices[${rank} - 2] * ${sh} - ${phStart} + j;
|
||||
`;
|
||||
}
|
||||
codeHEnd = `
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
const poolingCode = `
|
||||
float process(int indices[${rank}]) {
|
||||
int x[${rank}];
|
||||
copyVec(indices, x);
|
||||
|
||||
float value = ${start};
|
||||
int pad = 0;
|
||||
${codeH}
|
||||
${codeW}
|
||||
${codeHEnd}
|
||||
${op2}
|
||||
return value;
|
||||
}
|
||||
`;
|
||||
return poolingCode;
|
||||
} else {
|
||||
const kernelSize = ShapeUtil.size(attributes.kernelShape);
|
||||
const kernelStrides = ShapeUtil.computeStrides(attributes.kernelShape);
|
||||
const stridesRank = kernelStrides.length;
|
||||
const padsRank = attributes.pads.length;
|
||||
const offsetToIndicesFunction = offsetToIndices(stridesRank);
|
||||
const copyInputDims = copyArray(inputDims, 'inputDims');
|
||||
const copyPads = copyArray(attributes.pads, 'pads');
|
||||
const copyKernelStrides = copyArray(kernelStrides, 'kernelStrides');
|
||||
const copyStrides = copyArray(attributes.strides, 'strides');
|
||||
const hasPads = attributes.pads.reduce((sum, cur) => sum + cur);
|
||||
let padCode = '';
|
||||
if (hasPads) {
|
||||
padCode = `
|
||||
if (x[j] >= inputDims[j] || x[j] < 0) {
|
||||
pad++;
|
||||
isPad = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!isPad) {
|
||||
${op1}
|
||||
}`;
|
||||
} else {
|
||||
padCode = `
|
||||
}
|
||||
${op1}
|
||||
`;
|
||||
}
|
||||
const poolingCode = `
|
||||
${offsetToIndicesFunction}
|
||||
float process(int indices[${rank}]) {
|
||||
int x[${rank}];
|
||||
copyVec(indices, x);
|
||||
int offset[${stridesRank}];
|
||||
int pads[${padsRank}];
|
||||
int inputDims[${rank}];
|
||||
int kernelStrides[${stridesRank}];
|
||||
int strides[${stridesRank}];
|
||||
${copyPads}
|
||||
${copyInputDims}
|
||||
${copyStrides}
|
||||
${copyKernelStrides}
|
||||
|
||||
float value = ${start};
|
||||
int pad = 0;
|
||||
bool isPad = false;
|
||||
for (int i = 0; i < ${kernelSize}; i++) {
|
||||
offsetToIndices(i, kernelStrides, offset);
|
||||
isPad = false;
|
||||
for (int j = ${rank} - ${stridesRank}; j < ${rank}; j++) {
|
||||
x[j] = indices[j] * strides[j - ${rank} + ${stridesRank}]
|
||||
+ offset[j - ${rank} + ${stridesRank}] - pads[j - 2];
|
||||
${padCode}
|
||||
}
|
||||
${op2}
|
||||
|
||||
return value;
|
||||
}
|
||||
`;
|
||||
return poolingCode;
|
||||
}
|
||||
};
|
||||
|
||||
const copyArray = (array: readonly number[], arrayName: string): string => {
|
||||
let block = '';
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
block += `
|
||||
${arrayName}[${i}] = ${array[i]};
|
||||
`;
|
||||
}
|
||||
return block;
|
||||
};
|
||||
|
||||
const offsetToIndices = (rank: number): string => `
|
||||
void offsetToIndices(int offset, int[${rank}] strides, out int[${rank}] indices) {
|
||||
if (${rank} == 0) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < ${rank} - 1; ++i) {
|
||||
indices[i] = offset / strides[i];
|
||||
offset -= indices[i] * strides[i];
|
||||
}
|
||||
indices[${rank} - 1] = offset;
|
||||
}`;
|
||||
131
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/reduce.js
generated
vendored
Normal file
131
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/reduce.js
generated
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.reduceLogSumSquare = exports.reduceLogSum = exports.reduceProd = exports.reduceMin = exports.reduceMax = exports.reduceMean = exports.reduceSum = exports.parseReduceAttributes = void 0;
|
||||
const attribute_with_cache_key_1 = require("../../../attribute-with-cache-key");
|
||||
const operators_1 = require("../../../operators");
|
||||
const util_1 = require("../../../util");
|
||||
const types_1 = require("../types");
|
||||
const reduce = (inferenceHandler, inputs, attributes, name, reduceOp) => {
|
||||
validateInputs(inputs);
|
||||
const reduceProgramMetadata = {
|
||||
name,
|
||||
inputNames: ['A'],
|
||||
inputTypes: [types_1.TextureType.unpacked],
|
||||
};
|
||||
const output = inferenceHandler.run(Object.assign(Object.assign({}, reduceProgramMetadata), { cacheHint: attributes.cacheKey, get: () => createReduceProgramInfo(inferenceHandler, inputs, attributes, name, reduceOp, reduceProgramMetadata) }), inputs);
|
||||
return [output];
|
||||
};
|
||||
const parseReduceAttributes = (node) => {
|
||||
const axes = node.attributes.getInts('axes', []);
|
||||
const keepDims = node.attributes.getInt('keepdims', 1) === 1;
|
||||
return (0, attribute_with_cache_key_1.createAttributeWithCacheKey)({ axes, keepDims });
|
||||
};
|
||||
exports.parseReduceAttributes = parseReduceAttributes;
|
||||
const createReduceProgramInfo = (handler, inputs, attributes, name, reduceOp, reduceProgramMetadata) => {
|
||||
const outputShape = [];
|
||||
const iRank = inputs[0].dims.length || 1;
|
||||
const idxCopy = []; // copy output indexes to input indexes
|
||||
const axes = util_1.ShapeUtil.normalizeAxes(attributes.axes, inputs[0].dims.length);
|
||||
const ops = reduceOp(inputs, axes);
|
||||
let reduceOps = ops[1];
|
||||
for (let k = 0; k < inputs[0].dims.length; k++) {
|
||||
// if this axis is reduced
|
||||
if (axes.indexOf(k) >= 0 || axes.length === 0) {
|
||||
if (attributes.keepDims) {
|
||||
outputShape.push(1);
|
||||
} // else { remove the axis from outputShape; }
|
||||
// loop over the d-th axis
|
||||
reduceOps = `
|
||||
for(int j${k} = 0; j${k} < ${inputs[0].dims[k]}; j${k}++) {
|
||||
inputIdx[${k}] = j${k};
|
||||
${reduceOps}
|
||||
}`;
|
||||
}
|
||||
else {
|
||||
idxCopy.push(`inputIdx[${k}] = outputIdx[${outputShape.length}];`);
|
||||
outputShape.push(inputs[0].dims[k]);
|
||||
}
|
||||
}
|
||||
const oRank = outputShape.length || 1;
|
||||
const shaderSource = `
|
||||
float process(int outputIdx[${oRank}]) {
|
||||
float value; // final result
|
||||
int inputIdx[${iRank}]; // addressing input data
|
||||
${idxCopy.join('\n')}
|
||||
${ops[0]} // init ops for reduce max/min
|
||||
${reduceOps}
|
||||
${ops[2]} // final computation for reduce mean
|
||||
return value;
|
||||
}`;
|
||||
return Object.assign(Object.assign({}, reduceProgramMetadata), { output: { dims: outputShape, type: inputs[0].type, textureType: types_1.TextureType.unpacked }, shaderSource });
|
||||
};
|
||||
const validateInputs = (inputs) => {
|
||||
if (!inputs || inputs.length !== 1) {
|
||||
throw new Error('Reduce op requires 1 input.');
|
||||
}
|
||||
if (operators_1.NUMBER_TYPES.indexOf(inputs[0].type) === -1) {
|
||||
throw new Error('Invalid input type.');
|
||||
}
|
||||
};
|
||||
const reduceSum = (inferenceHandler, inputs, attributes) => {
|
||||
const reduceOp = () => ['value = 0.0;', 'value += _A(inputIdx);', ''];
|
||||
return reduce(inferenceHandler, inputs, attributes, 'ReduceSum', reduceOp);
|
||||
};
|
||||
exports.reduceSum = reduceSum;
|
||||
const reduceMean = (inferenceHandler, inputs, attributes) => {
|
||||
const reduceOp = (inputs, axes) => {
|
||||
let size = 1.0;
|
||||
for (let k = 0; k < inputs[0].dims.length; k++) {
|
||||
if (axes.indexOf(k) >= 0 || axes.length === 0) {
|
||||
size *= inputs[0].dims[k];
|
||||
}
|
||||
}
|
||||
return ['value = 0.0;', 'value += _A(inputIdx);', `value /= ${size}.;`]; // ensure real number with `.`
|
||||
};
|
||||
return reduce(inferenceHandler, inputs, attributes, 'ReduceMean', reduceOp);
|
||||
};
|
||||
exports.reduceMean = reduceMean;
|
||||
const reduceMax = (inferenceHandler, inputs, attributes) => {
|
||||
const reduceOp = (inputs, axes) => {
|
||||
const idxZero = [];
|
||||
for (let k = 0; k < inputs[0].dims.length; k++) {
|
||||
if (axes.indexOf(k) >= 0 || axes.length === 0) {
|
||||
idxZero.push(`inputIdx[${k}] = 0;`); // first element
|
||||
}
|
||||
}
|
||||
return [`${idxZero.join('\n')}\nvalue = _A(inputIdx);`, 'value = max(value, _A(inputIdx));', ''];
|
||||
};
|
||||
return reduce(inferenceHandler, inputs, attributes, 'ReduceMax', reduceOp);
|
||||
};
|
||||
exports.reduceMax = reduceMax;
|
||||
const reduceMin = (inferenceHandler, inputs, attributes) => {
|
||||
const reduceOp = (inputs, axes) => {
|
||||
const idxZero = [];
|
||||
for (let k = 0; k < inputs[0].dims.length; k++) {
|
||||
if (axes.indexOf(k) >= 0 || axes.length === 0) {
|
||||
idxZero.push(`inputIdx[${k}] = 0;`); // first element
|
||||
}
|
||||
}
|
||||
return [`${idxZero.join('\n')}\nvalue = _A(inputIdx);`, 'value = min(value, _A(inputIdx));', ''];
|
||||
};
|
||||
return reduce(inferenceHandler, inputs, attributes, 'ReduceMin', reduceOp);
|
||||
};
|
||||
exports.reduceMin = reduceMin;
|
||||
const reduceProd = (inferenceHandler, inputs, attributes) => {
|
||||
const reduceOp = () => ['value = 1.0;', 'value *= _A(inputIdx);', ''];
|
||||
return reduce(inferenceHandler, inputs, attributes, 'ReduceProd', reduceOp);
|
||||
};
|
||||
exports.reduceProd = reduceProd;
|
||||
const reduceLogSum = (inferenceHandler, inputs, attributes) => {
|
||||
const reduceOp = () => ['value = 0.0;', 'value += _A(inputIdx);', 'value = log(value);'];
|
||||
return reduce(inferenceHandler, inputs, attributes, 'ReduceLogSum', reduceOp);
|
||||
};
|
||||
exports.reduceLogSum = reduceLogSum;
|
||||
const reduceLogSumSquare = (inferenceHandler, inputs, attributes) => {
|
||||
const reduceOp = () => ['float t; value = 0.0;', 't = _A(inputIdx); value += t * t;', ''];
|
||||
return reduce(inferenceHandler, inputs, attributes, 'ReduceLogSumSquare', reduceOp);
|
||||
};
|
||||
exports.reduceLogSumSquare = reduceLogSumSquare;
|
||||
//# sourceMappingURL=reduce.js.map
|
||||
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/reduce.js.map
generated
vendored
Normal file
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/reduce.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
177
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/reduce.ts
generated
vendored
Normal file
177
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/reduce.ts
generated
vendored
Normal file
@@ -0,0 +1,177 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../../../attribute-with-cache-key';
|
||||
import {Graph} from '../../../graph';
|
||||
import {NUMBER_TYPES, OperatorImplementation, OperatorInitialization} from '../../../operators';
|
||||
import {Tensor} from '../../../tensor';
|
||||
import {ShapeUtil} from '../../../util';
|
||||
import {WebGLInferenceHandler} from '../inference-handler';
|
||||
import {ProgramInfo, ProgramMetadata, TextureType} from '../types';
|
||||
|
||||
export interface ReduceAttributes extends AttributeWithCacheKey {
|
||||
readonly axes: number[];
|
||||
readonly keepDims: boolean;
|
||||
}
|
||||
|
||||
// return [init ops, reduce ops, final ops]
|
||||
type ReduceOp = (inputs: Tensor[], axes: number[]) => string[];
|
||||
|
||||
const reduce =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: ReduceAttributes, name: string,
|
||||
reduceOp: ReduceOp): Tensor[] => {
|
||||
validateInputs(inputs);
|
||||
|
||||
const reduceProgramMetadata = {
|
||||
name,
|
||||
inputNames: ['A'],
|
||||
inputTypes: [TextureType.unpacked],
|
||||
};
|
||||
|
||||
const output = inferenceHandler.run(
|
||||
{
|
||||
...reduceProgramMetadata,
|
||||
cacheHint: attributes.cacheKey,
|
||||
get: () =>
|
||||
createReduceProgramInfo(inferenceHandler, inputs, attributes, name, reduceOp, reduceProgramMetadata)
|
||||
},
|
||||
inputs);
|
||||
return [output];
|
||||
};
|
||||
|
||||
export const parseReduceAttributes: OperatorInitialization<ReduceAttributes> = (node: Graph.Node): ReduceAttributes => {
|
||||
const axes = node.attributes.getInts('axes', []);
|
||||
const keepDims = node.attributes.getInt('keepdims', 1) === 1;
|
||||
return createAttributeWithCacheKey({axes, keepDims});
|
||||
};
|
||||
|
||||
const createReduceProgramInfo =
|
||||
(handler: WebGLInferenceHandler, inputs: Tensor[], attributes: ReduceAttributes, name: string, reduceOp: ReduceOp,
|
||||
reduceProgramMetadata: ProgramMetadata): ProgramInfo => {
|
||||
const outputShape: number[] = [];
|
||||
const iRank = inputs[0].dims.length || 1;
|
||||
|
||||
const idxCopy = []; // copy output indexes to input indexes
|
||||
|
||||
const axes = ShapeUtil.normalizeAxes(attributes.axes, inputs[0].dims.length);
|
||||
const ops = reduceOp(inputs, axes);
|
||||
let reduceOps = ops[1];
|
||||
|
||||
for (let k = 0; k < inputs[0].dims.length; k++) {
|
||||
// if this axis is reduced
|
||||
if (axes.indexOf(k) >= 0 || axes.length === 0) {
|
||||
if (attributes.keepDims) {
|
||||
outputShape.push(1);
|
||||
} // else { remove the axis from outputShape; }
|
||||
|
||||
// loop over the d-th axis
|
||||
reduceOps = `
|
||||
for(int j${k} = 0; j${k} < ${inputs[0].dims[k]}; j${k}++) {
|
||||
inputIdx[${k}] = j${k};
|
||||
${reduceOps}
|
||||
}`;
|
||||
} else {
|
||||
idxCopy.push(`inputIdx[${k}] = outputIdx[${outputShape.length}];`);
|
||||
|
||||
outputShape.push(inputs[0].dims[k]);
|
||||
}
|
||||
}
|
||||
|
||||
const oRank = outputShape.length || 1;
|
||||
|
||||
const shaderSource = `
|
||||
float process(int outputIdx[${oRank}]) {
|
||||
float value; // final result
|
||||
int inputIdx[${iRank}]; // addressing input data
|
||||
${idxCopy.join('\n')}
|
||||
${ops[0]} // init ops for reduce max/min
|
||||
${reduceOps}
|
||||
${ops[2]} // final computation for reduce mean
|
||||
return value;
|
||||
}`;
|
||||
|
||||
return {
|
||||
...reduceProgramMetadata,
|
||||
output: {dims: outputShape, type: inputs[0].type, textureType: TextureType.unpacked},
|
||||
shaderSource
|
||||
};
|
||||
};
|
||||
|
||||
const validateInputs = (inputs: Tensor[]): void => {
|
||||
if (!inputs || inputs.length !== 1) {
|
||||
throw new Error('Reduce op requires 1 input.');
|
||||
}
|
||||
|
||||
if (NUMBER_TYPES.indexOf(inputs[0].type) === -1) {
|
||||
throw new Error('Invalid input type.');
|
||||
}
|
||||
};
|
||||
|
||||
export const reduceSum: OperatorImplementation<ReduceAttributes> =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: ReduceAttributes): Tensor[] => {
|
||||
const reduceOp: ReduceOp = (): string[] => ['value = 0.0;', 'value += _A(inputIdx);', ''];
|
||||
return reduce(inferenceHandler, inputs, attributes, 'ReduceSum', reduceOp);
|
||||
};
|
||||
|
||||
export const reduceMean: OperatorImplementation<ReduceAttributes> =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: ReduceAttributes): Tensor[] => {
|
||||
const reduceOp: ReduceOp = (inputs: Tensor[], axes: number[]): string[] => {
|
||||
let size = 1.0;
|
||||
for (let k = 0; k < inputs[0].dims.length; k++) {
|
||||
if (axes.indexOf(k) >= 0 || axes.length === 0) {
|
||||
size *= inputs[0].dims[k];
|
||||
}
|
||||
}
|
||||
|
||||
return ['value = 0.0;', 'value += _A(inputIdx);', `value /= ${size}.;`]; // ensure real number with `.`
|
||||
};
|
||||
return reduce(inferenceHandler, inputs, attributes, 'ReduceMean', reduceOp);
|
||||
};
|
||||
|
||||
export const reduceMax: OperatorImplementation<ReduceAttributes> =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: ReduceAttributes): Tensor[] => {
|
||||
const reduceOp: ReduceOp = (inputs: Tensor[], axes: number[]): string[] => {
|
||||
const idxZero = [];
|
||||
for (let k = 0; k < inputs[0].dims.length; k++) {
|
||||
if (axes.indexOf(k) >= 0 || axes.length === 0) {
|
||||
idxZero.push(`inputIdx[${k}] = 0;`); // first element
|
||||
}
|
||||
}
|
||||
|
||||
return [`${idxZero.join('\n')}\nvalue = _A(inputIdx);`, 'value = max(value, _A(inputIdx));', ''];
|
||||
};
|
||||
return reduce(inferenceHandler, inputs, attributes, 'ReduceMax', reduceOp);
|
||||
};
|
||||
|
||||
export const reduceMin: OperatorImplementation<ReduceAttributes> =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: ReduceAttributes): Tensor[] => {
|
||||
const reduceOp: ReduceOp = (inputs: Tensor[], axes: number[]): string[] => {
|
||||
const idxZero = [];
|
||||
for (let k = 0; k < inputs[0].dims.length; k++) {
|
||||
if (axes.indexOf(k) >= 0 || axes.length === 0) {
|
||||
idxZero.push(`inputIdx[${k}] = 0;`); // first element
|
||||
}
|
||||
}
|
||||
|
||||
return [`${idxZero.join('\n')}\nvalue = _A(inputIdx);`, 'value = min(value, _A(inputIdx));', ''];
|
||||
};
|
||||
return reduce(inferenceHandler, inputs, attributes, 'ReduceMin', reduceOp);
|
||||
};
|
||||
|
||||
export const reduceProd: OperatorImplementation<ReduceAttributes> =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: ReduceAttributes): Tensor[] => {
|
||||
const reduceOp: ReduceOp = (): string[] => ['value = 1.0;', 'value *= _A(inputIdx);', ''];
|
||||
return reduce(inferenceHandler, inputs, attributes, 'ReduceProd', reduceOp);
|
||||
};
|
||||
|
||||
export const reduceLogSum: OperatorImplementation<ReduceAttributes> =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: ReduceAttributes): Tensor[] => {
|
||||
const reduceOp: ReduceOp = (): string[] => ['value = 0.0;', 'value += _A(inputIdx);', 'value = log(value);'];
|
||||
return reduce(inferenceHandler, inputs, attributes, 'ReduceLogSum', reduceOp);
|
||||
};
|
||||
|
||||
export const reduceLogSumSquare: OperatorImplementation<ReduceAttributes> =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: ReduceAttributes): Tensor[] => {
|
||||
const reduceOp: ReduceOp = (): string[] => ['float t; value = 0.0;', 't = _A(inputIdx); value += t * t;', ''];
|
||||
return reduce(inferenceHandler, inputs, attributes, 'ReduceLogSumSquare', reduceOp);
|
||||
};
|
||||
139
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/reshape-packed.js
generated
vendored
Normal file
139
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/reshape-packed.js
generated
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.isReshapeCheap = exports.processDims3D = exports.createPackedReshape3DProgramInfoLoader = void 0;
|
||||
const util_1 = require("../../../util");
|
||||
const glsl_source_1 = require("../glsl-source");
|
||||
const types_1 = require("../types");
|
||||
const packing_utils_1 = require("./packing-utils");
|
||||
const createPackedReshape3DProgramMetadata = (outputShape3D) => ({ name: 'Reshape (packed)', inputTypes: [types_1.TextureType.packed], inputNames: ['A'], cacheHint: `${outputShape3D}` });
|
||||
const createPackedReshape3DProgramInfo = (handler, input3D, metadata, outputShape3D) => {
|
||||
const inputShape3D = input3D.dims;
|
||||
const squeezedOutputShape = outputShape3D;
|
||||
let mainLoop = '';
|
||||
for (let i = 0; i < 4; i++) {
|
||||
let outputCoords = '';
|
||||
switch (i) {
|
||||
case 0:
|
||||
outputCoords = 'outputCoords = rc;';
|
||||
break;
|
||||
case 1:
|
||||
outputCoords = 'outputCoords = ivec3(rc.x, rc.y+1, rc.z);';
|
||||
break;
|
||||
case 2:
|
||||
outputCoords = 'outputCoords = ivec3(rc.x, rc.y, rc.z+1);';
|
||||
break;
|
||||
case 3:
|
||||
outputCoords = 'outputCoords = ivec3(rc.x, rc.y+1, rc.z+1);';
|
||||
break;
|
||||
default:
|
||||
throw new Error();
|
||||
}
|
||||
mainLoop += `
|
||||
${outputCoords}
|
||||
${i > 0 ? 'if(outputCoords.y < rows && outputCoords.z < cols){' : ''}
|
||||
int flattenedIndex = getFlattenedIndex(outputCoords);
|
||||
|
||||
ivec3 inputRC = inputCoordsFromReshapedOutCoords(flattenedIndex);
|
||||
vec2 innerDims = vec2(float(inputRC.y),float(inputRC.z));
|
||||
|
||||
result[${i}] = getChannel(getA(inputRC.x, inputRC.y, inputRC.z), innerDims);
|
||||
|
||||
${i > 0 ? '}' : ''}
|
||||
`;
|
||||
}
|
||||
const glsl = (0, glsl_source_1.getGlsl)(handler.session.backend.glContext.version);
|
||||
const shaderSource = `
|
||||
${getReshapedInputCoords(inputShape3D)}
|
||||
${getFlattenedIndexFrom3D(squeezedOutputShape)}
|
||||
${(0, packing_utils_1.unpackFromChannel)()}
|
||||
|
||||
void main() {
|
||||
ivec3 rc = getOutputCoords();
|
||||
|
||||
vec4 result = vec4(0.0);
|
||||
|
||||
ivec3 outputCoords;
|
||||
int rows = ${squeezedOutputShape[2]};
|
||||
int cols = ${squeezedOutputShape[1]};
|
||||
|
||||
${mainLoop}
|
||||
${glsl.output} = result;
|
||||
}
|
||||
`;
|
||||
return Object.assign(Object.assign({}, metadata), { output: { dims: squeezedOutputShape, type: input3D.type, textureType: types_1.TextureType.packed }, shaderSource, hasMain: true });
|
||||
};
|
||||
const createPackedReshape3DProgramInfoLoader = (handler, input3D, outputShape3D) => {
|
||||
const metadata = createPackedReshape3DProgramMetadata(outputShape3D);
|
||||
return Object.assign(Object.assign({}, metadata), { get: () => createPackedReshape3DProgramInfo(handler, input3D, metadata, outputShape3D) });
|
||||
};
|
||||
exports.createPackedReshape3DProgramInfoLoader = createPackedReshape3DProgramInfoLoader;
|
||||
function processDims3D(shape) {
|
||||
if (shape.length === 0) {
|
||||
return [1, 1, 1];
|
||||
}
|
||||
// TODO: squeeze other shapes to 2D case
|
||||
let batch = 1;
|
||||
for (let i = 0; i < shape.length - 2; ++i) {
|
||||
batch *= shape[i];
|
||||
}
|
||||
return [batch, shape.length > 1 ? shape[shape.length - 2] : 1, shape[shape.length - 1]];
|
||||
}
|
||||
exports.processDims3D = processDims3D;
|
||||
// For packed reshape, we need to re-arrange texel data for output shape.
|
||||
// Our pack is designed to pack a 2x2 tile in last h and w dimension, so
|
||||
// for the reshaped new tensor, we just need to re-arrange the last h and
|
||||
// w dimension. For any shape that is not in 3D, i.e. [batch, W, H], we
|
||||
// first convert it to 3D by collapsing other dimension to batch dim, then
|
||||
// process with the last two dimensions.
|
||||
// Note: we only need the shape tensor to calculate output shape, so the
|
||||
// content in shape tensor is never uploaded to GPU. It is always kept in CPU.
|
||||
// TODO: optimize the algorithm -- in some cases, if the last two dims are
|
||||
// the same between input shape and output shape, the packed reshape can be
|
||||
// treated as no-op.
|
||||
function isReshapeCheap(dims, reshapedDims) {
|
||||
let isCheapReshape = false;
|
||||
if (dims.length === 0 || reshapedDims.length === 0) { // scalar
|
||||
isCheapReshape = true;
|
||||
}
|
||||
else if (dims.length < 2 || reshapedDims.length < 2) { // 1D
|
||||
isCheapReshape = dims[dims.length - 1] === reshapedDims[reshapedDims.length - 1];
|
||||
}
|
||||
else { // 2D +
|
||||
isCheapReshape = dims[dims.length - 1] === reshapedDims[reshapedDims.length - 1] &&
|
||||
dims[dims.length - 2] === reshapedDims[reshapedDims.length - 2];
|
||||
}
|
||||
return isCheapReshape;
|
||||
}
|
||||
exports.isReshapeCheap = isReshapeCheap;
|
||||
function getReshapedInputCoords(shape) {
|
||||
const strides = util_1.ShapeUtil.computeStrides(shape);
|
||||
const coords = ['b', 'r', 'c'];
|
||||
const index = 'index';
|
||||
const coordsFromIndexSnippet = strides
|
||||
.map((stride, i) => {
|
||||
const line1 = `int ${coords[i]} = ${index} / ${stride}`;
|
||||
const line2 = i === strides.length - 1 ?
|
||||
`int ${coords[i + 1]} = ${index} - ${coords[i]} * ${stride}` :
|
||||
`index -= ${coords[i]} * ${stride}`;
|
||||
return `${line1}; ${line2};`;
|
||||
})
|
||||
.join('');
|
||||
return `
|
||||
ivec3 inputCoordsFromReshapedOutCoords(int index) {
|
||||
${coordsFromIndexSnippet}
|
||||
return ivec3(b, r, c);
|
||||
}
|
||||
`;
|
||||
}
|
||||
function getFlattenedIndexFrom3D(shape) {
|
||||
const strides = util_1.ShapeUtil.computeStrides(shape);
|
||||
return `
|
||||
int getFlattenedIndex(ivec3 coords) {
|
||||
// reverse y, z order
|
||||
return coords.x * ${strides[0]} + coords.z * ${strides[1]} + coords.y;
|
||||
}
|
||||
`;
|
||||
}
|
||||
//# sourceMappingURL=reshape-packed.js.map
|
||||
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/reshape-packed.js.map
generated
vendored
Normal file
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/reshape-packed.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"reshape-packed.js","sourceRoot":"","sources":["reshape-packed.ts"],"names":[],"mappings":"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"}
|
||||
157
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/reshape-packed.ts
generated
vendored
Normal file
157
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/reshape-packed.ts
generated
vendored
Normal file
@@ -0,0 +1,157 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import {Tensor} from '../../../tensor';
|
||||
import {ShapeUtil} from '../../../util';
|
||||
import {getGlsl} from '../glsl-source';
|
||||
import {WebGLInferenceHandler} from '../inference-handler';
|
||||
import {ProgramInfo, ProgramInfoLoader, ProgramMetadata, TextureType} from '../types';
|
||||
|
||||
import {unpackFromChannel} from './packing-utils';
|
||||
|
||||
const createPackedReshape3DProgramMetadata = (outputShape3D: readonly number[]) =>
|
||||
({name: 'Reshape (packed)', inputTypes: [TextureType.packed], inputNames: ['A'], cacheHint: `${outputShape3D}`});
|
||||
|
||||
const createPackedReshape3DProgramInfo =
|
||||
(handler: WebGLInferenceHandler, input3D: Tensor, metadata: ProgramMetadata, outputShape3D: readonly number[]):
|
||||
ProgramInfo => {
|
||||
const inputShape3D = input3D.dims as [number, number, number];
|
||||
const squeezedOutputShape = outputShape3D as [number, number, number];
|
||||
|
||||
let mainLoop = '';
|
||||
for (let i = 0; i < 4; i++) {
|
||||
let outputCoords = '';
|
||||
switch (i) {
|
||||
case 0:
|
||||
outputCoords = 'outputCoords = rc;';
|
||||
break;
|
||||
case 1:
|
||||
outputCoords = 'outputCoords = ivec3(rc.x, rc.y+1, rc.z);';
|
||||
break;
|
||||
case 2:
|
||||
outputCoords = 'outputCoords = ivec3(rc.x, rc.y, rc.z+1);';
|
||||
break;
|
||||
case 3:
|
||||
outputCoords = 'outputCoords = ivec3(rc.x, rc.y+1, rc.z+1);';
|
||||
break;
|
||||
default:
|
||||
throw new Error();
|
||||
}
|
||||
|
||||
mainLoop += `
|
||||
${outputCoords}
|
||||
${i > 0 ? 'if(outputCoords.y < rows && outputCoords.z < cols){' : ''}
|
||||
int flattenedIndex = getFlattenedIndex(outputCoords);
|
||||
|
||||
ivec3 inputRC = inputCoordsFromReshapedOutCoords(flattenedIndex);
|
||||
vec2 innerDims = vec2(float(inputRC.y),float(inputRC.z));
|
||||
|
||||
result[${i}] = getChannel(getA(inputRC.x, inputRC.y, inputRC.z), innerDims);
|
||||
|
||||
${i > 0 ? '}' : ''}
|
||||
`;
|
||||
}
|
||||
const glsl = getGlsl(handler.session.backend.glContext.version);
|
||||
|
||||
const shaderSource = `
|
||||
${getReshapedInputCoords(inputShape3D)}
|
||||
${getFlattenedIndexFrom3D(squeezedOutputShape)}
|
||||
${unpackFromChannel()}
|
||||
|
||||
void main() {
|
||||
ivec3 rc = getOutputCoords();
|
||||
|
||||
vec4 result = vec4(0.0);
|
||||
|
||||
ivec3 outputCoords;
|
||||
int rows = ${squeezedOutputShape[2]};
|
||||
int cols = ${squeezedOutputShape[1]};
|
||||
|
||||
${mainLoop}
|
||||
${glsl.output} = result;
|
||||
}
|
||||
`;
|
||||
|
||||
return {
|
||||
...metadata,
|
||||
output: {dims: squeezedOutputShape, type: input3D.type, textureType: TextureType.packed},
|
||||
shaderSource,
|
||||
hasMain: true
|
||||
};
|
||||
};
|
||||
|
||||
export const createPackedReshape3DProgramInfoLoader =
|
||||
(handler: WebGLInferenceHandler, input3D: Tensor, outputShape3D: readonly number[]): ProgramInfoLoader => {
|
||||
const metadata = createPackedReshape3DProgramMetadata(outputShape3D);
|
||||
return {...metadata, get: () => createPackedReshape3DProgramInfo(handler, input3D, metadata, outputShape3D)};
|
||||
};
|
||||
|
||||
export function processDims3D(shape: ArrayLike<number>): [number, number, number] {
|
||||
if (shape.length === 0) {
|
||||
return [1, 1, 1];
|
||||
}
|
||||
// TODO: squeeze other shapes to 2D case
|
||||
let batch = 1;
|
||||
for (let i = 0; i < shape.length - 2; ++i) {
|
||||
batch *= shape[i];
|
||||
}
|
||||
return [batch, shape.length > 1 ? shape[shape.length - 2] : 1, shape[shape.length - 1]];
|
||||
}
|
||||
|
||||
// For packed reshape, we need to re-arrange texel data for output shape.
|
||||
// Our pack is designed to pack a 2x2 tile in last h and w dimension, so
|
||||
// for the reshaped new tensor, we just need to re-arrange the last h and
|
||||
// w dimension. For any shape that is not in 3D, i.e. [batch, W, H], we
|
||||
// first convert it to 3D by collapsing other dimension to batch dim, then
|
||||
// process with the last two dimensions.
|
||||
// Note: we only need the shape tensor to calculate output shape, so the
|
||||
// content in shape tensor is never uploaded to GPU. It is always kept in CPU.
|
||||
// TODO: optimize the algorithm -- in some cases, if the last two dims are
|
||||
// the same between input shape and output shape, the packed reshape can be
|
||||
// treated as no-op.
|
||||
export function isReshapeCheap(dims: readonly number[], reshapedDims: readonly number[]) {
|
||||
let isCheapReshape = false;
|
||||
if (dims.length === 0 || reshapedDims.length === 0) { // scalar
|
||||
isCheapReshape = true;
|
||||
} else if (dims.length < 2 || reshapedDims.length < 2) { // 1D
|
||||
isCheapReshape = dims[dims.length - 1] === reshapedDims[reshapedDims.length - 1];
|
||||
} else { // 2D +
|
||||
isCheapReshape = dims[dims.length - 1] === reshapedDims[reshapedDims.length - 1] &&
|
||||
dims[dims.length - 2] === reshapedDims[reshapedDims.length - 2];
|
||||
}
|
||||
|
||||
return isCheapReshape;
|
||||
}
|
||||
|
||||
function getReshapedInputCoords(shape: [number, number, number]): string {
|
||||
const strides = ShapeUtil.computeStrides(shape);
|
||||
const coords = ['b', 'r', 'c'];
|
||||
const index = 'index';
|
||||
const coordsFromIndexSnippet = strides
|
||||
.map((stride, i) => {
|
||||
const line1 = `int ${coords[i]} = ${index} / ${stride}`;
|
||||
const line2 = i === strides.length - 1 ?
|
||||
`int ${coords[i + 1]} = ${index} - ${coords[i]} * ${stride}` :
|
||||
`index -= ${coords[i]} * ${stride}`;
|
||||
return `${line1}; ${line2};`;
|
||||
})
|
||||
.join('');
|
||||
|
||||
return `
|
||||
ivec3 inputCoordsFromReshapedOutCoords(int index) {
|
||||
${coordsFromIndexSnippet}
|
||||
return ivec3(b, r, c);
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
function getFlattenedIndexFrom3D(shape: [number, number, number]): string {
|
||||
const strides = ShapeUtil.computeStrides(shape);
|
||||
|
||||
return `
|
||||
int getFlattenedIndex(ivec3 coords) {
|
||||
// reverse y, z order
|
||||
return coords.x * ${strides[0]} + coords.z * ${strides[1]} + coords.y;
|
||||
}
|
||||
`;
|
||||
}
|
||||
17
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/reshape.js
generated
vendored
Normal file
17
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/reshape.js
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.reshape = void 0;
|
||||
const util_1 = require("../../../util");
|
||||
const reshape = (handler, inputs) => {
|
||||
const reshapedDims = util_1.ShapeUtil.calculateReshapedDims(inputs[0].dims, inputs[1].integerData);
|
||||
if (handler.session.pack) {
|
||||
return [handler.reshapePacked(inputs[0], reshapedDims)];
|
||||
}
|
||||
else {
|
||||
return [handler.reshapeUnpacked(inputs[0], reshapedDims)];
|
||||
}
|
||||
};
|
||||
exports.reshape = reshape;
|
||||
//# sourceMappingURL=reshape.js.map
|
||||
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/reshape.js.map
generated
vendored
Normal file
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/reshape.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"reshape.js","sourceRoot":"","sources":["reshape.ts"],"names":[],"mappings":";AAAA,4DAA4D;AAC5D,kCAAkC;;;AAGlC,wCAAwC;AAGjC,MAAM,OAAO,GAAG,CAAC,OAA8B,EAAE,MAAgB,EAAY,EAAE;IACpF,MAAM,YAAY,GAAG,gBAAS,CAAC,qBAAqB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;IAC5F,IAAI,OAAO,CAAC,OAAO,CAAC,IAAI,EAAE;QACxB,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC;KACzD;SAAM;QACL,OAAO,CAAC,OAAO,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC;KAC3D;AACH,CAAC,CAAC;AAPW,QAAA,OAAO,WAOlB"}
|
||||
15
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/reshape.ts
generated
vendored
Normal file
15
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/reshape.ts
generated
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import {Tensor} from '../../../tensor';
|
||||
import {ShapeUtil} from '../../../util';
|
||||
import {WebGLInferenceHandler} from '../inference-handler';
|
||||
|
||||
export const reshape = (handler: WebGLInferenceHandler, inputs: Tensor[]): Tensor[] => {
|
||||
const reshapedDims = ShapeUtil.calculateReshapedDims(inputs[0].dims, inputs[1].integerData);
|
||||
if (handler.session.pack) {
|
||||
return [handler.reshapePacked(inputs[0], reshapedDims)];
|
||||
} else {
|
||||
return [handler.reshapeUnpacked(inputs[0], reshapedDims)];
|
||||
}
|
||||
};
|
||||
238
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/resize-packed.js
generated
vendored
Normal file
238
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/resize-packed.js
generated
vendored
Normal file
@@ -0,0 +1,238 @@
|
||||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.parseResizeAttributesV11 = exports.parseResizeAttributesV10 = exports.resize = void 0;
|
||||
const glsl_source_1 = require("../glsl-source");
|
||||
const types_1 = require("../types");
|
||||
const utils_1 = require("../utils");
|
||||
const packing_utils_1 = require("./packing-utils");
|
||||
const upsample_1 = require("./upsample");
|
||||
const resizeProgramMetadata = {
|
||||
name: 'Resize',
|
||||
inputNames: ['A'],
|
||||
inputTypes: [types_1.TextureType.packed]
|
||||
};
|
||||
const resize = (inferenceHandler, inputs, attributes) => {
|
||||
(0, upsample_1.validateInputs)(inputs, attributes);
|
||||
const output = inferenceHandler.run(Object.assign(Object.assign({}, resizeProgramMetadata), { cacheHint: attributes.cacheKey, get: () => createPackedResizeProgramInfo(inferenceHandler, inputs, attributes) }), inputs);
|
||||
return [output];
|
||||
};
|
||||
exports.resize = resize;
|
||||
const parseResizeAttributesV10 = (node) => (0, upsample_1.parseUpsampleAttributes)(node, 10);
|
||||
exports.parseResizeAttributesV10 = parseResizeAttributesV10;
|
||||
const parseResizeAttributesV11 = (node) => (0, upsample_1.parseUpsampleAttributes)(node, 11);
|
||||
exports.parseResizeAttributesV11 = parseResizeAttributesV11;
|
||||
const createPackedResizeProgramInfo = (inferenceHandler, inputs, attributes) => {
|
||||
const glsl = (0, glsl_source_1.getGlsl)(inferenceHandler.session.backend.glContext.version);
|
||||
const [scales, outputShape] = prepareInputs(inputs, attributes);
|
||||
const isSame = scales.every((s) => s === 1) && attributes.coordinateTransformMode !== 'tf_crop_and_resize';
|
||||
if (isSame) {
|
||||
return Object.assign(Object.assign({}, resizeProgramMetadata), { output: { dims: outputShape, type: inputs[0].type, textureType: types_1.TextureType.packed }, hasMain: true, shaderSource: `void main() {
|
||||
vec4 v = ${glsl.texture2D}(X, TexCoords);
|
||||
${glsl.output} = v;
|
||||
}` });
|
||||
}
|
||||
const dim = outputShape.length;
|
||||
if (dim < 2) {
|
||||
throw new Error(`output dimension should be at least 2, but got ${dim}`);
|
||||
}
|
||||
const outputHeight = outputShape[dim - 2];
|
||||
const outputWidth = outputShape[dim - 1];
|
||||
const inputShape = inputs[0].dims;
|
||||
if (dim !== inputShape.length) {
|
||||
throw new Error(`output dimension should match input ${inputShape.length}, but got ${dim}`);
|
||||
}
|
||||
const inputHeight = inputShape[dim - 2];
|
||||
const inputWidth = inputShape[dim - 1];
|
||||
const scalesHeight = scales[dim - 2];
|
||||
const scalesWidth = scales[dim - 1];
|
||||
let getSourceFracIndex = '';
|
||||
if (attributes.mode !== 'linear') {
|
||||
// TODO: support other modes
|
||||
throw new Error(`resize (packed) does not support mode: '${attributes.mode}'`);
|
||||
}
|
||||
switch (attributes.coordinateTransformMode) {
|
||||
case 'asymmetric':
|
||||
getSourceFracIndex = `
|
||||
vec4 getSourceFracIndex(ivec4 coords) {
|
||||
return vec4(coords) / scaleWHWH;
|
||||
}
|
||||
`;
|
||||
break;
|
||||
case 'half_pixel':
|
||||
getSourceFracIndex = `
|
||||
vec4 getSourceFracIndex(ivec4 coords) {
|
||||
return (vec4(coords) + 0.5) / scaleWHWH - 0.5;
|
||||
}
|
||||
`;
|
||||
break;
|
||||
case 'pytorch_half_pixel':
|
||||
getSourceFracIndex = `
|
||||
vec4 getSourceFracIndex(ivec4 coords) {
|
||||
vec4 fcoords = vec4(coords);
|
||||
return vec4(
|
||||
${outputWidth}.0 > 1.0 ? (fcoords.x + 0.5) / scaleWHWH.x - 0.5 : 0.0,
|
||||
${outputHeight}.0 > 1.0 ? (fcoords.y + 0.5) / scaleWHWH.y - 0.5 : 0.0,
|
||||
${outputWidth}.0 > 1.0 ? (fcoords.z + 0.5) / scaleWHWH.z - 0.5 : 0.0,
|
||||
${outputHeight}.0 > 1.0 ? (fcoords.w + 0.5) / scaleWHWH.w - 0.5 : 0.0
|
||||
);
|
||||
}
|
||||
`;
|
||||
break;
|
||||
case 'align_corners':
|
||||
getSourceFracIndex = `
|
||||
vec4 getSourceFracIndex(ivec4 coords) {
|
||||
vec4 resized = vec4(${outputWidth}.0 - 1.0, ${outputHeight}.0 - 1.0, ${outputWidth}.0 - 1.0,
|
||||
${outputHeight}.0 - 1.0);
|
||||
vec4 original = vec4(${inputWidth}.0 - 1.0, ${inputHeight}.0 - 1.0, ${inputWidth}.0 - 1.0,
|
||||
${inputHeight}.0 - 1.0);
|
||||
vec4 new_scale = original / resized;
|
||||
return vec4(coords) * new_scale;
|
||||
}
|
||||
`;
|
||||
break;
|
||||
default:
|
||||
// TODO:supporting other coordinateTransformModes
|
||||
throw new Error(`resize (packed) does not support coordinateTransformMode: \
|
||||
'${attributes.coordinateTransformMode}'`);
|
||||
}
|
||||
const coordsDataType = (0, utils_1.getCoordsDataType)(dim);
|
||||
const unpackChannel = (0, packing_utils_1.unpackFromChannel)();
|
||||
const shaderSource = `
|
||||
const vec2 inputWH = vec2(${inputHeight}.0, ${inputWidth}.0);
|
||||
const vec4 scaleWHWH = vec4(float(${scalesHeight}), float(${scalesWidth}), float(${scalesHeight}), float(${scalesWidth}));
|
||||
${unpackChannel}
|
||||
${getSourceFracIndex}
|
||||
float getAValue(int x10, int r, int c, int d) {
|
||||
return getChannel(getA(x10, r, c, d), vec2(c, d));
|
||||
}
|
||||
void main() {
|
||||
${coordsDataType} rc = getOutputCoords();
|
||||
|
||||
int batch = rc[0];
|
||||
int depth = rc[1];
|
||||
|
||||
// retrieve the 4 coordinates that is used in the 4 packed output values.
|
||||
ivec4 coords = ivec4(rc.wz, rc.w + 1, rc.z + 1);
|
||||
|
||||
// calculate the source index in fraction
|
||||
vec4 sourceFrac = getSourceFracIndex(coords);
|
||||
|
||||
// get the lower and upper bound of the 4 values that will be packed into one texel.
|
||||
ivec4 x00 = ivec4(max(sourceFrac.xy, vec2(0.0)), min(inputWH - 1.0, ceil(sourceFrac.xy)));
|
||||
ivec4 x01 = ivec4(max(sourceFrac.xw, vec2(0.0)), min(inputWH - 1.0, ceil(sourceFrac.xw)));
|
||||
ivec4 x10 = ivec4(max(sourceFrac.zy, vec2(0.0)), min(inputWH - 1.0, ceil(sourceFrac.zy)));
|
||||
ivec4 x11 = ivec4(max(sourceFrac.zw, vec2(0.0)), min(inputWH - 1.0, ceil(sourceFrac.zw)));
|
||||
|
||||
bool hasNextRow = rc.w < ${outputHeight - 1};
|
||||
bool hasNextCol = rc.z < ${outputWidth - 1};
|
||||
|
||||
// pack x00, x01, x10, x11's top-left corner into one vec4 structure
|
||||
vec4 topLeft = vec4(
|
||||
getAValue(batch, depth, x00.x, x00.y),
|
||||
hasNextCol ? getAValue(batch, depth, x01.x, x01.y) : 0.0,
|
||||
hasNextRow ? getAValue(batch, depth, x10.x, x10.y) : 0.0,
|
||||
(hasNextRow && hasNextCol) ? getAValue(batch, depth, x11.x, x11.y) : 0.0);
|
||||
|
||||
// pack x00, x01, x10, x11's top-right corner into one vec4 structure
|
||||
vec4 topRight = vec4(
|
||||
getAValue(batch, depth, x00.x, x00.w),
|
||||
hasNextCol ? getAValue(batch, depth, x01.x, x01.w) : 0.0,
|
||||
hasNextRow ? getAValue(batch, depth, x10.x, x10.w) : 0.0,
|
||||
(hasNextRow && hasNextCol) ? getAValue(batch, depth, x11.x, x11.w) : 0.0);
|
||||
|
||||
// pack x00, x01, x10, x11's bottom-left corner into one vec4 structure
|
||||
vec4 bottomLeft = vec4(
|
||||
getAValue(batch, depth, x00.z, x00.y),
|
||||
hasNextCol ? getAValue(batch, depth, x01.z, x01.y) : 0.0,
|
||||
hasNextRow ? getAValue(batch, depth, x10.z, x10.y) : 0.0,
|
||||
(hasNextRow && hasNextCol) ? getAValue(batch, depth, x11.z, x11.y) : 0.0);
|
||||
|
||||
// pack x00, x01, x10, x11's bottom-right corner into one vec4 structure
|
||||
vec4 bottomRight = vec4(
|
||||
getAValue(batch, depth, x00.z, x00.w),
|
||||
hasNextCol ? getAValue(batch, depth, x01.z, x01.w) : 0.0,
|
||||
hasNextRow ? getAValue(batch, depth, x10.z, x10.w) : 0.0,
|
||||
(hasNextRow && hasNextCol) ? getAValue(batch, depth, x11.z, x11.w) : 0.0);
|
||||
|
||||
// calculate the interpolation fraction on u and v direction
|
||||
vec4 frac = vec4(sourceFrac) - floor(sourceFrac);
|
||||
vec4 clampFrac = clamp(frac, vec4(0.0), vec4(1.0));
|
||||
|
||||
vec4 top = mix(topLeft, topRight, clampFrac.ywyw);
|
||||
vec4 bottom = mix(bottomLeft, bottomRight, clampFrac.ywyw);
|
||||
vec4 newValue = mix(top, bottom, clampFrac.xxzz);
|
||||
|
||||
${glsl.output} = vec4(newValue);
|
||||
}
|
||||
`;
|
||||
return Object.assign(Object.assign({}, resizeProgramMetadata), { output: { dims: outputShape, type: inputs[0].type, textureType: types_1.TextureType.packed }, hasMain: true, shaderSource });
|
||||
};
|
||||
const prepareInputs = (inputs, attributes) => {
|
||||
const x = inputs[0];
|
||||
const xDims = x.dims;
|
||||
let scales = attributes.scales;
|
||||
let outputSizes;
|
||||
if (scales.length === 0) {
|
||||
const scalesTensor = inputs[attributes.scalesInputIdx];
|
||||
if (scalesTensor && scalesTensor.size !== 0) {
|
||||
if (inputs[attributes.sizesInputIdx]) {
|
||||
throw new Error('Only one of scales or sizes must be provided as input.');
|
||||
}
|
||||
scales = parseScalesData(scalesTensor, attributes.mode, attributes.isResize);
|
||||
}
|
||||
else {
|
||||
const sizesTensor = inputs[attributes.sizesInputIdx];
|
||||
if (!sizesTensor || sizesTensor.size === 0) {
|
||||
throw new Error('Either scales or sizes MUST be provided as input.');
|
||||
}
|
||||
outputSizes = Array.from(sizesTensor.integerData);
|
||||
scales = parseScalesDataFromOutputSize(outputSizes, xDims, attributes.mode, attributes.isResize);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (inputs[attributes.sizesInputIdx]) {
|
||||
throw new Error('Only one of scales or sizes must be provided as input.');
|
||||
}
|
||||
}
|
||||
const yDims = outputSizes || (xDims.map((dim, i) => Math.floor(dim * scales[i])));
|
||||
return [scales, yDims];
|
||||
};
|
||||
const parseScalesData = (scale, mode, isResize) => {
|
||||
const scales = Array.from(scale.floatData);
|
||||
(0, upsample_1.scalesValidation)(scales, mode, isResize);
|
||||
return scales;
|
||||
};
|
||||
const parseScalesDataFromOutputSize = (yDims, xDims, mode, isResize) => {
|
||||
const length = xDims.length;
|
||||
const scales = new Array(length);
|
||||
for (let i = 0, end = length; i < end; i++) {
|
||||
if (xDims[i] === 0) {
|
||||
if (yDims[i] !== 0) {
|
||||
throw new Error('Input dim is zero but required output dim is non-zero.');
|
||||
}
|
||||
scales[i] = 1;
|
||||
}
|
||||
else {
|
||||
scales[i] = yDims[i] / xDims[i];
|
||||
}
|
||||
}
|
||||
(0, upsample_1.scalesValidation)(scales, mode, isResize);
|
||||
return scales;
|
||||
};
|
||||
// roi data is not used yet. but leave here for future usage.
|
||||
// const getRoi = (inputs: Tensor[], attributes: UpsampleAttributes) : number[] => {
|
||||
// let roi: number[] = [];
|
||||
// if (attributes.needRoiInput) {
|
||||
// if (attributes.roiInputIdx <= 0) {
|
||||
// throw new Error('Invalid roi input index.');
|
||||
// }
|
||||
// const roiTensor = inputs[attributes.roiInputIdx];
|
||||
// roi = roiTensor.size > 0 ? Array.from(roiTensor.floatData) : [];
|
||||
// } else {
|
||||
// roi = new Array(inputs[0].dims.length * 2).fill(0);
|
||||
// }
|
||||
// return roi;
|
||||
// };
|
||||
//# sourceMappingURL=resize-packed.js.map
|
||||
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/resize-packed.js.map
generated
vendored
Normal file
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/resize-packed.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
280
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/resize-packed.ts
generated
vendored
Normal file
280
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/resize-packed.ts
generated
vendored
Normal file
@@ -0,0 +1,280 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import {Graph} from '../../../graph';
|
||||
import {OperatorImplementation, OperatorInitialization} from '../../../operators';
|
||||
import {Tensor} from '../../../tensor';
|
||||
import {getGlsl} from '../glsl-source';
|
||||
import {WebGLInferenceHandler} from '../inference-handler';
|
||||
import {ProgramInfo, TextureType} from '../types';
|
||||
import {getCoordsDataType} from '../utils';
|
||||
|
||||
import {unpackFromChannel} from './packing-utils';
|
||||
import {parseUpsampleAttributes, scalesValidation, UpsampleAttributes, validateInputs} from './upsample';
|
||||
|
||||
const resizeProgramMetadata = {
|
||||
name: 'Resize',
|
||||
inputNames: ['A'],
|
||||
inputTypes: [TextureType.packed]
|
||||
};
|
||||
|
||||
export const resize: OperatorImplementation<UpsampleAttributes> =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: UpsampleAttributes): Tensor[] => {
|
||||
validateInputs(inputs, attributes);
|
||||
const output = inferenceHandler.run(
|
||||
{
|
||||
...resizeProgramMetadata,
|
||||
cacheHint: attributes.cacheKey,
|
||||
get: () => createPackedResizeProgramInfo(inferenceHandler, inputs, attributes)
|
||||
},
|
||||
inputs);
|
||||
return [output];
|
||||
};
|
||||
|
||||
export const parseResizeAttributesV10: OperatorInitialization<UpsampleAttributes> =
|
||||
(node: Graph.Node): UpsampleAttributes => parseUpsampleAttributes(node, 10);
|
||||
|
||||
export const parseResizeAttributesV11: OperatorInitialization<UpsampleAttributes> =
|
||||
(node: Graph.Node): UpsampleAttributes => parseUpsampleAttributes(node, 11);
|
||||
|
||||
const createPackedResizeProgramInfo =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: UpsampleAttributes): ProgramInfo => {
|
||||
const glsl = getGlsl(inferenceHandler.session.backend.glContext.version);
|
||||
const [scales, outputShape] = prepareInputs(inputs, attributes);
|
||||
|
||||
const isSame =
|
||||
scales.every((s: number) => s === 1) && attributes.coordinateTransformMode !== 'tf_crop_and_resize';
|
||||
if (isSame) {
|
||||
return {
|
||||
...resizeProgramMetadata,
|
||||
output: {dims: outputShape, type: inputs[0].type, textureType: TextureType.packed},
|
||||
hasMain: true,
|
||||
shaderSource: `void main() {
|
||||
vec4 v = ${glsl.texture2D}(X, TexCoords);
|
||||
${glsl.output} = v;
|
||||
}`
|
||||
};
|
||||
}
|
||||
|
||||
const dim = outputShape.length;
|
||||
if (dim < 2) {
|
||||
throw new Error(`output dimension should be at least 2, but got ${dim}`);
|
||||
}
|
||||
|
||||
const outputHeight = outputShape[dim - 2];
|
||||
const outputWidth = outputShape[dim - 1];
|
||||
|
||||
const inputShape = inputs[0].dims;
|
||||
if (dim !== inputShape.length) {
|
||||
throw new Error(`output dimension should match input ${inputShape.length}, but got ${dim}`);
|
||||
}
|
||||
const inputHeight = inputShape[dim - 2];
|
||||
const inputWidth = inputShape[dim - 1];
|
||||
|
||||
const scalesHeight = scales[dim - 2];
|
||||
const scalesWidth = scales[dim - 1];
|
||||
|
||||
let getSourceFracIndex = '';
|
||||
|
||||
if (attributes.mode !== 'linear') {
|
||||
// TODO: support other modes
|
||||
throw new Error(`resize (packed) does not support mode: '${attributes.mode}'`);
|
||||
}
|
||||
switch (attributes.coordinateTransformMode) {
|
||||
case 'asymmetric':
|
||||
getSourceFracIndex = `
|
||||
vec4 getSourceFracIndex(ivec4 coords) {
|
||||
return vec4(coords) / scaleWHWH;
|
||||
}
|
||||
`;
|
||||
break;
|
||||
case 'half_pixel':
|
||||
getSourceFracIndex = `
|
||||
vec4 getSourceFracIndex(ivec4 coords) {
|
||||
return (vec4(coords) + 0.5) / scaleWHWH - 0.5;
|
||||
}
|
||||
`;
|
||||
break;
|
||||
case 'pytorch_half_pixel':
|
||||
getSourceFracIndex = `
|
||||
vec4 getSourceFracIndex(ivec4 coords) {
|
||||
vec4 fcoords = vec4(coords);
|
||||
return vec4(
|
||||
${outputWidth}.0 > 1.0 ? (fcoords.x + 0.5) / scaleWHWH.x - 0.5 : 0.0,
|
||||
${outputHeight}.0 > 1.0 ? (fcoords.y + 0.5) / scaleWHWH.y - 0.5 : 0.0,
|
||||
${outputWidth}.0 > 1.0 ? (fcoords.z + 0.5) / scaleWHWH.z - 0.5 : 0.0,
|
||||
${outputHeight}.0 > 1.0 ? (fcoords.w + 0.5) / scaleWHWH.w - 0.5 : 0.0
|
||||
);
|
||||
}
|
||||
`;
|
||||
break;
|
||||
case 'align_corners':
|
||||
getSourceFracIndex = `
|
||||
vec4 getSourceFracIndex(ivec4 coords) {
|
||||
vec4 resized = vec4(${outputWidth}.0 - 1.0, ${outputHeight}.0 - 1.0, ${outputWidth}.0 - 1.0,
|
||||
${outputHeight}.0 - 1.0);
|
||||
vec4 original = vec4(${inputWidth}.0 - 1.0, ${inputHeight}.0 - 1.0, ${inputWidth}.0 - 1.0,
|
||||
${inputHeight}.0 - 1.0);
|
||||
vec4 new_scale = original / resized;
|
||||
return vec4(coords) * new_scale;
|
||||
}
|
||||
`;
|
||||
break;
|
||||
default:
|
||||
// TODO:supporting other coordinateTransformModes
|
||||
throw new Error(`resize (packed) does not support coordinateTransformMode: \
|
||||
'${attributes.coordinateTransformMode}'`);
|
||||
}
|
||||
|
||||
const coordsDataType = getCoordsDataType(dim);
|
||||
const unpackChannel = unpackFromChannel();
|
||||
const shaderSource = `
|
||||
const vec2 inputWH = vec2(${inputHeight}.0, ${inputWidth}.0);
|
||||
const vec4 scaleWHWH = vec4(float(${scalesHeight}), float(${scalesWidth}), float(${scalesHeight}), float(${
|
||||
scalesWidth}));
|
||||
${unpackChannel}
|
||||
${getSourceFracIndex}
|
||||
float getAValue(int x10, int r, int c, int d) {
|
||||
return getChannel(getA(x10, r, c, d), vec2(c, d));
|
||||
}
|
||||
void main() {
|
||||
${coordsDataType} rc = getOutputCoords();
|
||||
|
||||
int batch = rc[0];
|
||||
int depth = rc[1];
|
||||
|
||||
// retrieve the 4 coordinates that is used in the 4 packed output values.
|
||||
ivec4 coords = ivec4(rc.wz, rc.w + 1, rc.z + 1);
|
||||
|
||||
// calculate the source index in fraction
|
||||
vec4 sourceFrac = getSourceFracIndex(coords);
|
||||
|
||||
// get the lower and upper bound of the 4 values that will be packed into one texel.
|
||||
ivec4 x00 = ivec4(max(sourceFrac.xy, vec2(0.0)), min(inputWH - 1.0, ceil(sourceFrac.xy)));
|
||||
ivec4 x01 = ivec4(max(sourceFrac.xw, vec2(0.0)), min(inputWH - 1.0, ceil(sourceFrac.xw)));
|
||||
ivec4 x10 = ivec4(max(sourceFrac.zy, vec2(0.0)), min(inputWH - 1.0, ceil(sourceFrac.zy)));
|
||||
ivec4 x11 = ivec4(max(sourceFrac.zw, vec2(0.0)), min(inputWH - 1.0, ceil(sourceFrac.zw)));
|
||||
|
||||
bool hasNextRow = rc.w < ${outputHeight - 1};
|
||||
bool hasNextCol = rc.z < ${outputWidth - 1};
|
||||
|
||||
// pack x00, x01, x10, x11's top-left corner into one vec4 structure
|
||||
vec4 topLeft = vec4(
|
||||
getAValue(batch, depth, x00.x, x00.y),
|
||||
hasNextCol ? getAValue(batch, depth, x01.x, x01.y) : 0.0,
|
||||
hasNextRow ? getAValue(batch, depth, x10.x, x10.y) : 0.0,
|
||||
(hasNextRow && hasNextCol) ? getAValue(batch, depth, x11.x, x11.y) : 0.0);
|
||||
|
||||
// pack x00, x01, x10, x11's top-right corner into one vec4 structure
|
||||
vec4 topRight = vec4(
|
||||
getAValue(batch, depth, x00.x, x00.w),
|
||||
hasNextCol ? getAValue(batch, depth, x01.x, x01.w) : 0.0,
|
||||
hasNextRow ? getAValue(batch, depth, x10.x, x10.w) : 0.0,
|
||||
(hasNextRow && hasNextCol) ? getAValue(batch, depth, x11.x, x11.w) : 0.0);
|
||||
|
||||
// pack x00, x01, x10, x11's bottom-left corner into one vec4 structure
|
||||
vec4 bottomLeft = vec4(
|
||||
getAValue(batch, depth, x00.z, x00.y),
|
||||
hasNextCol ? getAValue(batch, depth, x01.z, x01.y) : 0.0,
|
||||
hasNextRow ? getAValue(batch, depth, x10.z, x10.y) : 0.0,
|
||||
(hasNextRow && hasNextCol) ? getAValue(batch, depth, x11.z, x11.y) : 0.0);
|
||||
|
||||
// pack x00, x01, x10, x11's bottom-right corner into one vec4 structure
|
||||
vec4 bottomRight = vec4(
|
||||
getAValue(batch, depth, x00.z, x00.w),
|
||||
hasNextCol ? getAValue(batch, depth, x01.z, x01.w) : 0.0,
|
||||
hasNextRow ? getAValue(batch, depth, x10.z, x10.w) : 0.0,
|
||||
(hasNextRow && hasNextCol) ? getAValue(batch, depth, x11.z, x11.w) : 0.0);
|
||||
|
||||
// calculate the interpolation fraction on u and v direction
|
||||
vec4 frac = vec4(sourceFrac) - floor(sourceFrac);
|
||||
vec4 clampFrac = clamp(frac, vec4(0.0), vec4(1.0));
|
||||
|
||||
vec4 top = mix(topLeft, topRight, clampFrac.ywyw);
|
||||
vec4 bottom = mix(bottomLeft, bottomRight, clampFrac.ywyw);
|
||||
vec4 newValue = mix(top, bottom, clampFrac.xxzz);
|
||||
|
||||
${glsl.output} = vec4(newValue);
|
||||
}
|
||||
`;
|
||||
return {
|
||||
...resizeProgramMetadata,
|
||||
output: {dims: outputShape, type: inputs[0].type, textureType: TextureType.packed},
|
||||
hasMain: true,
|
||||
shaderSource
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
const prepareInputs = (inputs: Tensor[], attributes: UpsampleAttributes): [readonly number[], readonly number[]] => {
|
||||
const x = inputs[0];
|
||||
const xDims = x.dims;
|
||||
|
||||
let scales = attributes.scales;
|
||||
let outputSizes: number[]|undefined;
|
||||
if (scales.length === 0) {
|
||||
const scalesTensor = inputs[attributes.scalesInputIdx];
|
||||
if (scalesTensor && scalesTensor.size !== 0) {
|
||||
if (inputs[attributes.sizesInputIdx]) {
|
||||
throw new Error('Only one of scales or sizes must be provided as input.');
|
||||
}
|
||||
scales = parseScalesData(scalesTensor, attributes.mode, attributes.isResize);
|
||||
} else {
|
||||
const sizesTensor = inputs[attributes.sizesInputIdx];
|
||||
if (!sizesTensor || sizesTensor.size === 0) {
|
||||
throw new Error('Either scales or sizes MUST be provided as input.');
|
||||
}
|
||||
|
||||
outputSizes = Array.from(sizesTensor.integerData);
|
||||
scales = parseScalesDataFromOutputSize(outputSizes, xDims, attributes.mode, attributes.isResize);
|
||||
}
|
||||
} else {
|
||||
if (inputs[attributes.sizesInputIdx]) {
|
||||
throw new Error('Only one of scales or sizes must be provided as input.');
|
||||
}
|
||||
}
|
||||
|
||||
const yDims = outputSizes || (xDims.map((dim, i) => Math.floor(dim * scales[i])));
|
||||
|
||||
return [scales, yDims];
|
||||
};
|
||||
|
||||
const parseScalesData = (scale: Tensor, mode: string, isResize: boolean): number[] => {
|
||||
const scales = Array.from(scale.floatData);
|
||||
scalesValidation(scales, mode, isResize);
|
||||
return scales;
|
||||
};
|
||||
|
||||
const parseScalesDataFromOutputSize =
|
||||
(yDims: readonly number[], xDims: readonly number[], mode: string, isResize: boolean): number[] => {
|
||||
const length = xDims.length;
|
||||
const scales = new Array<number>(length);
|
||||
|
||||
for (let i = 0, end = length; i < end; i++) {
|
||||
if (xDims[i] === 0) {
|
||||
if (yDims[i] !== 0) {
|
||||
throw new Error('Input dim is zero but required output dim is non-zero.');
|
||||
}
|
||||
scales[i] = 1;
|
||||
} else {
|
||||
scales[i] = yDims[i] / xDims[i];
|
||||
}
|
||||
}
|
||||
scalesValidation(scales, mode, isResize);
|
||||
return scales;
|
||||
};
|
||||
|
||||
// roi data is not used yet. but leave here for future usage.
|
||||
// const getRoi = (inputs: Tensor[], attributes: UpsampleAttributes) : number[] => {
|
||||
// let roi: number[] = [];
|
||||
// if (attributes.needRoiInput) {
|
||||
// if (attributes.roiInputIdx <= 0) {
|
||||
// throw new Error('Invalid roi input index.');
|
||||
// }
|
||||
// const roiTensor = inputs[attributes.roiInputIdx];
|
||||
// roi = roiTensor.size > 0 ? Array.from(roiTensor.floatData) : [];
|
||||
// } else {
|
||||
// roi = new Array(inputs[0].dims.length * 2).fill(0);
|
||||
// }
|
||||
// return roi;
|
||||
// };
|
||||
17
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/shape.js
generated
vendored
Normal file
17
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/shape.js
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.shape = void 0;
|
||||
const tensor_1 = require("../../../tensor");
|
||||
const shape = (inferenceHandler, inputs) => {
|
||||
validateInputs(inputs);
|
||||
return [new tensor_1.Tensor([inputs[0].dims.length], 'int32', undefined, undefined, new Int32Array(inputs[0].dims))];
|
||||
};
|
||||
exports.shape = shape;
|
||||
const validateInputs = (inputs) => {
|
||||
if (!inputs || inputs.length !== 1) {
|
||||
throw new Error('Shape requires 1 input.');
|
||||
}
|
||||
};
|
||||
//# sourceMappingURL=shape.js.map
|
||||
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/shape.js.map
generated
vendored
Normal file
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/shape.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"shape.js","sourceRoot":"","sources":["shape.ts"],"names":[],"mappings":";AAAA,4DAA4D;AAC5D,kCAAkC;;;AAElC,4CAAuC;AAGhC,MAAM,KAAK,GAAG,CAAC,gBAAuC,EAAE,MAAgB,EAAY,EAAE;IAC3F,cAAc,CAAC,MAAM,CAAC,CAAC;IACvB,OAAO,CAAC,IAAI,eAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC9G,CAAC,CAAC;AAHW,QAAA,KAAK,SAGhB;AAEF,MAAM,cAAc,GAAG,CAAC,MAAgB,EAAQ,EAAE;IAChD,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE;QAClC,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;KAC5C;AACH,CAAC,CAAC"}
|
||||
16
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/shape.ts
generated
vendored
Normal file
16
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/shape.ts
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import {Tensor} from '../../../tensor';
|
||||
import {WebGLInferenceHandler} from '../inference-handler';
|
||||
|
||||
export const shape = (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[]): Tensor[] => {
|
||||
validateInputs(inputs);
|
||||
return [new Tensor([inputs[0].dims.length], 'int32', undefined, undefined, new Int32Array(inputs[0].dims))];
|
||||
};
|
||||
|
||||
const validateInputs = (inputs: Tensor[]): void => {
|
||||
if (!inputs || inputs.length !== 1) {
|
||||
throw new Error('Shape requires 1 input.');
|
||||
}
|
||||
};
|
||||
107
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/slice.js
generated
vendored
Normal file
107
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/slice.js
generated
vendored
Normal file
@@ -0,0 +1,107 @@
|
||||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.sliceV10 = exports.parseSliceAttributes = exports.slice = void 0;
|
||||
const attribute_with_cache_key_1 = require("../../../attribute-with-cache-key");
|
||||
const operators_1 = require("../../../operators");
|
||||
const util_1 = require("../../../util");
|
||||
const types_1 = require("../types");
|
||||
const sliceProgramMetadata = {
|
||||
name: 'Slice',
|
||||
inputNames: ['A'],
|
||||
inputTypes: [types_1.TextureType.unpacked]
|
||||
};
|
||||
const slice = (inferenceHandler, inputs, attributes) => {
|
||||
validateInputs(inputs);
|
||||
const output = inferenceHandler.run(Object.assign(Object.assign({}, sliceProgramMetadata), { cacheHint: attributes.cacheKey, get: () => createSliceProgramInfo(inferenceHandler, inputs[0], attributes) }), inputs);
|
||||
return [output];
|
||||
};
|
||||
exports.slice = slice;
|
||||
const parseSliceAttributes = (node) => {
|
||||
const starts = node.attributes.getInts('starts');
|
||||
const ends = node.attributes.getInts('ends');
|
||||
const axes = node.attributes.getInts('axes', []);
|
||||
return (0, attribute_with_cache_key_1.createAttributeWithCacheKey)({ starts, ends, axes });
|
||||
};
|
||||
exports.parseSliceAttributes = parseSliceAttributes;
|
||||
const createSliceProgramInfo = (inferenceHandler, input, attributes) => {
|
||||
const axes = (attributes.axes.length === 0) ? input.dims.slice(0).map((val, i) => i) : attributes.axes;
|
||||
const normalizedAxes = util_1.ShapeUtil.normalizeAxes(axes, input.dims.length);
|
||||
const starts = attributes.starts.map((start, i) => {
|
||||
if (start > input.dims[normalizedAxes[i]] - 1) {
|
||||
return input.dims[normalizedAxes[i]];
|
||||
}
|
||||
return util_1.ShapeUtil.normalizeAxis(start, input.dims[normalizedAxes[i]]);
|
||||
});
|
||||
const ends = attributes.ends.map((end, i) => {
|
||||
if (end > input.dims[normalizedAxes[i]] - 1) {
|
||||
return input.dims[normalizedAxes[i]];
|
||||
}
|
||||
return util_1.ShapeUtil.normalizeAxis(end, input.dims[normalizedAxes[i]]);
|
||||
});
|
||||
const outputShape = input.dims.slice();
|
||||
const sliceOps = [];
|
||||
for (let i = 0; i < normalizedAxes.length; i++) {
|
||||
outputShape[normalizedAxes[i]] = ends[i] - starts[i];
|
||||
if (starts[i] > 0) {
|
||||
sliceOps.push(`outputIdx[${normalizedAxes[i]}] += ${starts[i]};`);
|
||||
} // else { sliceOps.push(`outputIdx[${normalizedAxes[i]}] += 0;`); }
|
||||
}
|
||||
const rank = outputShape.length;
|
||||
const shaderSource = `
|
||||
float process(int outputIdx[${rank}]) {
|
||||
${sliceOps.join('\n ')}
|
||||
return _A(outputIdx);
|
||||
}`;
|
||||
return Object.assign(Object.assign({}, sliceProgramMetadata), { output: { dims: outputShape, type: input.type, textureType: types_1.TextureType.unpacked }, shaderSource });
|
||||
};
|
||||
const validateInputs = (inputs) => {
|
||||
if (!inputs || inputs.length !== 1) {
|
||||
throw new Error('Slice requires 1 input.');
|
||||
}
|
||||
if (operators_1.NUMBER_TYPES.indexOf(inputs[0].type) === -1) {
|
||||
throw new Error('Invalid input type.');
|
||||
}
|
||||
};
|
||||
const sliceV10 = (inferenceHandler, inputs) => {
|
||||
validateInputsV10(inputs);
|
||||
const attributes = generateSliceAttributesFromInputs(inferenceHandler, inputs);
|
||||
const output = inferenceHandler.run(Object.assign(Object.assign({}, sliceProgramMetadata), { cacheHint: attributes.cacheKey, get: () => createSliceProgramInfo(inferenceHandler, inputs[0], attributes) }), [inputs[0]]);
|
||||
return [output];
|
||||
};
|
||||
exports.sliceV10 = sliceV10;
|
||||
const generateSliceAttributesFromInputs = (inferenceHandler, inputs) => {
|
||||
if (!inferenceHandler.session.isInitializer(inputs[1].dataId) ||
|
||||
!inferenceHandler.session.isInitializer(inputs[2].dataId) ||
|
||||
(inputs.length >= 4 && !inferenceHandler.session.isInitializer(inputs[3].dataId)) ||
|
||||
(inputs.length >= 5 && !inferenceHandler.session.isInitializer(inputs[4].dataId))) {
|
||||
throw new Error('dynamic slice attributes are not allowed');
|
||||
}
|
||||
if (inputs.length >= 5 && inputs[4].integerData.some((i) => i !== 1)) {
|
||||
throw new Error('currently non-1 steps is not supported for Slice');
|
||||
}
|
||||
const starts = Array.from(inputs[1].integerData);
|
||||
const ends = Array.from(inputs[2].integerData);
|
||||
const axes = inputs.length >= 4 ? Array.from(inputs[3].integerData) : [];
|
||||
const cacheKey = `${axes};${starts};${ends}`;
|
||||
return { starts, ends, axes, cacheKey };
|
||||
};
|
||||
const validateInputsV10 = (inputs) => {
|
||||
if (!inputs || inputs.length < 3 || inputs.length > 5) {
|
||||
throw new Error('Invalid input number.');
|
||||
}
|
||||
if (inputs[1].type !== 'int32' || inputs[1].dims.length !== 1) {
|
||||
throw new Error('Invalid input type.');
|
||||
}
|
||||
if (inputs[2].type !== 'int32' || inputs[2].dims.length !== 1) {
|
||||
throw new Error('Invalid input type.');
|
||||
}
|
||||
if (inputs.length >= 4 && (inputs[3].type !== 'int32' || inputs[3].dims.length !== 1)) {
|
||||
throw new Error('Invalid input type.');
|
||||
}
|
||||
if (inputs.length >= 5 && (inputs[4].type !== 'int32' || inputs[4].dims.length !== 1)) {
|
||||
throw new Error('Invalid input type.');
|
||||
}
|
||||
};
|
||||
//# sourceMappingURL=slice.js.map
|
||||
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/slice.js.map
generated
vendored
Normal file
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/slice.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
142
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/slice.ts
generated
vendored
Normal file
142
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/slice.ts
generated
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../../../attribute-with-cache-key';
|
||||
import {Graph} from '../../../graph';
|
||||
import {NUMBER_TYPES, OperatorImplementation, OperatorInitialization} from '../../../operators';
|
||||
import {Tensor} from '../../../tensor';
|
||||
import {ShapeUtil} from '../../../util';
|
||||
import {WebGLInferenceHandler} from '../inference-handler';
|
||||
import {ProgramInfo, TextureType} from '../types';
|
||||
|
||||
export interface SliceAttributes extends AttributeWithCacheKey {
|
||||
readonly axes: number[];
|
||||
readonly ends: number[];
|
||||
readonly starts: number[];
|
||||
}
|
||||
|
||||
const sliceProgramMetadata = {
|
||||
name: 'Slice',
|
||||
inputNames: ['A'],
|
||||
inputTypes: [TextureType.unpacked]
|
||||
};
|
||||
|
||||
export const slice: OperatorImplementation<SliceAttributes> =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: SliceAttributes): Tensor[] => {
|
||||
validateInputs(inputs);
|
||||
const output = inferenceHandler.run(
|
||||
{
|
||||
...sliceProgramMetadata,
|
||||
cacheHint: attributes.cacheKey,
|
||||
get: () => createSliceProgramInfo(inferenceHandler, inputs[0], attributes)
|
||||
},
|
||||
inputs);
|
||||
return [output];
|
||||
};
|
||||
|
||||
export const parseSliceAttributes: OperatorInitialization<SliceAttributes> = (node: Graph.Node): SliceAttributes => {
|
||||
const starts = node.attributes.getInts('starts');
|
||||
const ends = node.attributes.getInts('ends');
|
||||
const axes = node.attributes.getInts('axes', []);
|
||||
return createAttributeWithCacheKey({starts, ends, axes});
|
||||
};
|
||||
|
||||
const createSliceProgramInfo =
|
||||
(inferenceHandler: WebGLInferenceHandler, input: Tensor, attributes: SliceAttributes): ProgramInfo => {
|
||||
const axes = (attributes.axes.length === 0) ? input.dims.slice(0).map((val, i) => i) : attributes.axes;
|
||||
const normalizedAxes = ShapeUtil.normalizeAxes(axes, input.dims.length);
|
||||
const starts = attributes.starts.map((start, i) => {
|
||||
if (start > input.dims[normalizedAxes[i]] - 1) {
|
||||
return input.dims[normalizedAxes[i]];
|
||||
}
|
||||
return ShapeUtil.normalizeAxis(start, input.dims[normalizedAxes[i]]);
|
||||
});
|
||||
const ends = attributes.ends.map((end, i) => {
|
||||
if (end > input.dims[normalizedAxes[i]] - 1) {
|
||||
return input.dims[normalizedAxes[i]];
|
||||
}
|
||||
return ShapeUtil.normalizeAxis(end, input.dims[normalizedAxes[i]]);
|
||||
});
|
||||
|
||||
const outputShape = input.dims.slice();
|
||||
|
||||
const sliceOps: string[] = [];
|
||||
for (let i = 0; i < normalizedAxes.length; i++) {
|
||||
outputShape[normalizedAxes[i]] = ends[i] - starts[i];
|
||||
if (starts[i] > 0) {
|
||||
sliceOps.push(`outputIdx[${normalizedAxes[i]}] += ${starts[i]};`);
|
||||
} // else { sliceOps.push(`outputIdx[${normalizedAxes[i]}] += 0;`); }
|
||||
}
|
||||
|
||||
const rank = outputShape.length;
|
||||
const shaderSource = `
|
||||
float process(int outputIdx[${rank}]) {
|
||||
${sliceOps.join('\n ')}
|
||||
return _A(outputIdx);
|
||||
}`;
|
||||
return {
|
||||
...sliceProgramMetadata,
|
||||
output: {dims: outputShape, type: input.type, textureType: TextureType.unpacked},
|
||||
shaderSource
|
||||
};
|
||||
};
|
||||
|
||||
const validateInputs = (inputs: Tensor[]): void => {
|
||||
if (!inputs || inputs.length !== 1) {
|
||||
throw new Error('Slice requires 1 input.');
|
||||
}
|
||||
if (NUMBER_TYPES.indexOf(inputs[0].type) === -1) {
|
||||
throw new Error('Invalid input type.');
|
||||
}
|
||||
};
|
||||
|
||||
export const sliceV10 = (inferenceHandler: WebGLInferenceHandler, inputs: Tensor[]): Tensor[] => {
|
||||
validateInputsV10(inputs);
|
||||
const attributes = generateSliceAttributesFromInputs(inferenceHandler, inputs);
|
||||
const output = inferenceHandler.run(
|
||||
{
|
||||
...sliceProgramMetadata,
|
||||
cacheHint: attributes.cacheKey,
|
||||
get: () => createSliceProgramInfo(inferenceHandler, inputs[0], attributes)
|
||||
},
|
||||
[inputs[0]]);
|
||||
return [output];
|
||||
};
|
||||
|
||||
const generateSliceAttributesFromInputs =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: Tensor[]): SliceAttributes => {
|
||||
if (!inferenceHandler.session.isInitializer(inputs[1].dataId) ||
|
||||
!inferenceHandler.session.isInitializer(inputs[2].dataId) ||
|
||||
(inputs.length >= 4 && !inferenceHandler.session.isInitializer(inputs[3].dataId)) ||
|
||||
(inputs.length >= 5 && !inferenceHandler.session.isInitializer(inputs[4].dataId))) {
|
||||
throw new Error('dynamic slice attributes are not allowed');
|
||||
}
|
||||
|
||||
if (inputs.length >= 5 && inputs[4].integerData.some((i: number) => i !== 1)) {
|
||||
throw new Error('currently non-1 steps is not supported for Slice');
|
||||
}
|
||||
|
||||
const starts = Array.from(inputs[1].integerData);
|
||||
const ends = Array.from(inputs[2].integerData);
|
||||
const axes = inputs.length >= 4 ? Array.from(inputs[3].integerData) : [];
|
||||
const cacheKey = `${axes};${starts};${ends}`;
|
||||
return {starts, ends, axes, cacheKey};
|
||||
};
|
||||
|
||||
const validateInputsV10 = (inputs: Tensor[]): void => {
|
||||
if (!inputs || inputs.length < 3 || inputs.length > 5) {
|
||||
throw new Error('Invalid input number.');
|
||||
}
|
||||
if (inputs[1].type !== 'int32' || inputs[1].dims.length !== 1) {
|
||||
throw new Error('Invalid input type.');
|
||||
}
|
||||
if (inputs[2].type !== 'int32' || inputs[2].dims.length !== 1) {
|
||||
throw new Error('Invalid input type.');
|
||||
}
|
||||
if (inputs.length >= 4 && (inputs[3].type !== 'int32' || inputs[3].dims.length !== 1)) {
|
||||
throw new Error('Invalid input type.');
|
||||
}
|
||||
if (inputs.length >= 5 && (inputs[4].type !== 'int32' || inputs[4].dims.length !== 1)) {
|
||||
throw new Error('Invalid input type.');
|
||||
}
|
||||
};
|
||||
202
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/softmax.js
generated
vendored
Normal file
202
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/softmax.js
generated
vendored
Normal file
@@ -0,0 +1,202 @@
|
||||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.softmaxV13 = exports.parseSoftmaxAttributesV13 = exports.parseSoftmaxAttributes = exports.softmax = void 0;
|
||||
const attribute_with_cache_key_1 = require("../../../attribute-with-cache-key");
|
||||
const util_1 = require("../../../util");
|
||||
const glsl_source_1 = require("../glsl-source");
|
||||
const types_1 = require("../types");
|
||||
const transpose_1 = require("./transpose");
|
||||
const softmaxComputeMaxProgramMetadata = {
|
||||
name: 'SoftmaxComputeMax',
|
||||
inputNames: ['A'],
|
||||
inputTypes: [types_1.TextureType.unpacked],
|
||||
};
|
||||
const softmaxComputeScaleProgramMetadata = {
|
||||
name: 'SoftmaxComputeScale',
|
||||
inputNames: ['A', 'Max'],
|
||||
inputTypes: [types_1.TextureType.unpacked, types_1.TextureType.unpacked],
|
||||
};
|
||||
const softmaxProgramMetadata = {
|
||||
name: 'SoftMax',
|
||||
inputNames: ['A', 'Max', 'Norm'],
|
||||
inputTypes: [types_1.TextureType.unpacked, types_1.TextureType.unpacked, types_1.TextureType.unpacked],
|
||||
};
|
||||
const softmax = (inferenceHandler, inputs, attributes) => {
|
||||
validateInputs(inputs);
|
||||
const inputShape = inputs[0].dims.slice();
|
||||
const axis = util_1.ShapeUtil.normalizeAxis(attributes.axis, inputShape.length);
|
||||
const logicalRowCount = util_1.ShapeUtil.sizeToDimension(inputShape, axis);
|
||||
const featureCount = util_1.ShapeUtil.sizeFromDimension(inputShape, axis);
|
||||
const output = computeSoftmax(inferenceHandler, inputs, attributes, logicalRowCount, featureCount);
|
||||
return output;
|
||||
};
|
||||
exports.softmax = softmax;
|
||||
const parseSoftmaxAttributes = (node) => (0, attribute_with_cache_key_1.createAttributeWithCacheKey)({ axis: node.attributes.getInt('axis', 1) });
|
||||
exports.parseSoftmaxAttributes = parseSoftmaxAttributes;
|
||||
const parseSoftmaxAttributesV13 = (node) => (0, attribute_with_cache_key_1.createAttributeWithCacheKey)({ axis: node.attributes.getInt('axis', -1) });
|
||||
exports.parseSoftmaxAttributesV13 = parseSoftmaxAttributesV13;
|
||||
// The "semantic" meaning of axis has changed in opset-13.
|
||||
// Please compare: https://github.com/onnx/onnx/blob/main/docs/Operators.md#Softmax
|
||||
// with https://github.com/onnx/onnx/blob/main/docs/Changelog.md#Softmax-11 for detailed explanations
|
||||
// To account for the opset-13 behavior, our plan will be to transpose the "axis" dim to the innermost dim
|
||||
// and perform softmax and then reverse the transpose. We can skip the transposing aspect if the axis is already
|
||||
// the innermost dim
|
||||
const softmaxV13 = (inferenceHandler, inputs, attributes) => {
|
||||
validateInputs(inputs);
|
||||
const inputShape = inputs[0].dims.slice();
|
||||
const axis = util_1.ShapeUtil.normalizeAxis(attributes.axis, inputShape.length);
|
||||
const rank = inputShape.length;
|
||||
const isTransposeRequired = (axis !== rank - 1) ? true : false;
|
||||
const transposedInputShape = [];
|
||||
let perm = [];
|
||||
let transposedInputs = [];
|
||||
let transposeAttribute;
|
||||
if (isTransposeRequired) {
|
||||
perm = Array.from({ length: rank }).map((_, i) => i);
|
||||
// swap the innermost dim with the dim corresponding to axis
|
||||
perm[axis] = rank - 1;
|
||||
perm[rank - 1] = axis;
|
||||
perm.map(p => transposedInputShape.push(inputShape[p]));
|
||||
transposeAttribute = (0, attribute_with_cache_key_1.createAttributeWithCacheKey)({ perm });
|
||||
transposedInputs = (0, transpose_1.transpose)(inferenceHandler, inputs, transposeAttribute);
|
||||
}
|
||||
const logicalRowCount = isTransposeRequired ? util_1.ShapeUtil.sizeToDimension(transposedInputShape, rank - 1) :
|
||||
util_1.ShapeUtil.sizeToDimension(inputShape, rank - 1);
|
||||
const featureCount = isTransposeRequired ? util_1.ShapeUtil.sizeFromDimension(transposedInputShape, rank - 1) :
|
||||
util_1.ShapeUtil.sizeFromDimension(inputShape, rank - 1);
|
||||
const output = computeSoftmax(inferenceHandler, isTransposeRequired ? transposedInputs : inputs, attributes, logicalRowCount, featureCount);
|
||||
if (isTransposeRequired) {
|
||||
const reversedOutput = (0, transpose_1.transpose)(inferenceHandler, output, transposeAttribute);
|
||||
return reversedOutput;
|
||||
}
|
||||
else {
|
||||
return output;
|
||||
}
|
||||
};
|
||||
exports.softmaxV13 = softmaxV13;
|
||||
const computeSoftmax = (inferenceHandler, inputs, attributes, logicalRowCount, featureCount) => {
|
||||
const computeMaxProgramInfo = createComputeMaxProgramInfo(inferenceHandler, inputs[0], logicalRowCount, featureCount, [logicalRowCount]);
|
||||
const max = inferenceHandler.run(Object.assign(Object.assign({}, softmaxComputeMaxProgramMetadata), { cacheHint: attributes.cacheKey, get: () => computeMaxProgramInfo }), inputs);
|
||||
const computeScaleProgramInfo = createComputScaleProgramInfo(inferenceHandler, inputs[0], logicalRowCount, featureCount, computeMaxProgramInfo.output.dims, [logicalRowCount]);
|
||||
const scale = inferenceHandler.run(Object.assign(Object.assign({}, softmaxComputeScaleProgramMetadata), { cacheHint: attributes.cacheKey, get: () => computeScaleProgramInfo }), [inputs[0], max]);
|
||||
const softMaxProgramInfo = createSoftMaxProgramInfo(inferenceHandler, inputs[0], logicalRowCount, featureCount, computeMaxProgramInfo.output.dims, computeScaleProgramInfo.output.dims);
|
||||
const output = inferenceHandler.run(Object.assign(Object.assign({}, softmaxProgramMetadata), { cacheHint: attributes.cacheKey, get: () => softMaxProgramInfo }), [inputs[0], max, scale]);
|
||||
return [output];
|
||||
};
|
||||
/**
|
||||
* Create a texture that contains the maximum value of each of the 'N' rows
|
||||
*/
|
||||
const createComputeMaxProgramInfo = (inferenceHandler, input, logicalRowCount, featureCount, outputShape) => {
|
||||
const [textureWidth, textureHeight] = inferenceHandler.calculateTextureWidthAndHeight(input.dims, types_1.TextureType.unpacked);
|
||||
const rank = outputShape.length;
|
||||
if (logicalRowCount < 1 || featureCount < 1) {
|
||||
throw new Error('Logical row count N and feature count D must be greater than or equal to 1');
|
||||
}
|
||||
if (outputShape.length !== 1) {
|
||||
throw new Error('Dimensionality of the output should be 1');
|
||||
}
|
||||
if (outputShape[0] !== logicalRowCount) {
|
||||
throw new Error('Shape of the output should be equal to logical row count');
|
||||
}
|
||||
const glsl = (0, glsl_source_1.getGlsl)(inferenceHandler.session.backend.glContext.version);
|
||||
const shaderSource = `
|
||||
float process(int[${rank}] indices) {
|
||||
int logical_row_start_offset = indices[0] * ${featureCount};
|
||||
|
||||
float max = getColorAsFloat(${glsl.texture2D}(A, offsetToCoords(logical_row_start_offset, ${textureWidth},
|
||||
${textureHeight} )));
|
||||
for(int i=1; i<${featureCount}; ++i)
|
||||
{
|
||||
float current = getColorAsFloat(${glsl.texture2D}(A, offsetToCoords(logical_row_start_offset + i,
|
||||
${textureWidth}, ${textureHeight})));
|
||||
if(current > max)
|
||||
max = current;
|
||||
}
|
||||
|
||||
return max;
|
||||
}`;
|
||||
return Object.assign(Object.assign({}, softmaxComputeMaxProgramMetadata), { output: { dims: outputShape, type: input.type, textureType: types_1.TextureType.unpacked }, shaderSource });
|
||||
};
|
||||
/**
|
||||
* Create a texture that contains the normalization factor for each of the 'N' rows
|
||||
*/
|
||||
const createComputScaleProgramInfo = (inferenceHandler, input, logicalRowCount, featureCount, maxElementPerLogicalRow, outputShape) => {
|
||||
const [textureWidth, textureHeight] = inferenceHandler.calculateTextureWidthAndHeight(input.dims, types_1.TextureType.unpacked);
|
||||
const rank = outputShape.length;
|
||||
if (logicalRowCount < 1 || featureCount < 1) {
|
||||
throw new Error('Logical row count N and feature count D must be greater than or equal to 1');
|
||||
}
|
||||
if (outputShape.length !== 1) {
|
||||
throw new Error('Dimensionality of the output should be 1');
|
||||
}
|
||||
if (outputShape[0] !== logicalRowCount) {
|
||||
throw new Error('Shape of the output should be equal to logical row count');
|
||||
}
|
||||
if (maxElementPerLogicalRow.length !== 1) {
|
||||
throw new Error('Dimensionality of the intermediate results should be 1');
|
||||
}
|
||||
if (maxElementPerLogicalRow[0] !== logicalRowCount) {
|
||||
throw new Error('Shape of the intermediate results should be equal to logical row count');
|
||||
}
|
||||
const glsl = (0, glsl_source_1.getGlsl)(inferenceHandler.session.backend.glContext.version);
|
||||
const shaderSource = `
|
||||
float process(int[${rank}] indices) {
|
||||
int logical_row_start_offset = indices[0] * ${featureCount};
|
||||
|
||||
float norm_factor = 0.0;
|
||||
float max = _Max(indices);
|
||||
for(int i=0; i<${featureCount}; ++i)
|
||||
{
|
||||
norm_factor += exp(getColorAsFloat(${glsl.texture2D}(A, offsetToCoords(logical_row_start_offset + i,
|
||||
${textureWidth}, ${textureHeight}))) - max);
|
||||
}
|
||||
|
||||
return norm_factor;
|
||||
}`;
|
||||
return Object.assign(Object.assign({}, softmaxComputeScaleProgramMetadata), { output: { dims: outputShape, type: input.type, textureType: types_1.TextureType.unpacked }, shaderSource });
|
||||
};
|
||||
const createSoftMaxProgramInfo = (inferenceHandler, input, logicalRowCount, featureCount, maxElementPerLogicalRow, normalizationPerLogicalRow) => {
|
||||
const [textureWidth, textureHeight] = inferenceHandler.calculateTextureWidthAndHeight(input.dims, types_1.TextureType.unpacked);
|
||||
const rank = input.dims.length;
|
||||
if (logicalRowCount < 1 || featureCount < 1) {
|
||||
throw new Error('Logical row count N and feature count D must be greater than or equal to 1');
|
||||
}
|
||||
if (maxElementPerLogicalRow.length !== 1 || normalizationPerLogicalRow.length !== 1) {
|
||||
throw new Error('Dimensionality of the intermediate results should be 1');
|
||||
}
|
||||
if (maxElementPerLogicalRow[0] !== logicalRowCount || normalizationPerLogicalRow[0] !== logicalRowCount) {
|
||||
throw new Error('Shape of the intermediate results should be equal to logical row count');
|
||||
}
|
||||
const shaderSource = `
|
||||
float process(int[${rank}] indices) {
|
||||
|
||||
// get offset of current logical tensor index from the 2-D texture coordinates (TexCoords)
|
||||
int offset = coordsToOffset(TexCoords, ${textureWidth}, ${textureHeight});
|
||||
|
||||
//determine the logical row for this index
|
||||
int logical_row_index[1];
|
||||
logical_row_index[0] = offset / ${featureCount};
|
||||
|
||||
float norm_factor = _Norm(logical_row_index);
|
||||
|
||||
// avoid possible division by 0
|
||||
// if norm_facor is 0, all elements are zero
|
||||
// if so, return 0
|
||||
if(norm_factor == 0.0)
|
||||
return 0.0;
|
||||
|
||||
return exp(_A(indices) - _Max(logical_row_index)) / norm_factor;
|
||||
}`;
|
||||
return Object.assign(Object.assign({}, softmaxProgramMetadata), { output: { dims: input.dims, type: input.type, textureType: types_1.TextureType.unpacked }, shaderSource });
|
||||
};
|
||||
const validateInputs = (inputs) => {
|
||||
if (!inputs || inputs.length !== 1) {
|
||||
throw new Error('Softmax requires 1 input.');
|
||||
}
|
||||
if (inputs[0].type !== 'float32' && inputs[0].type !== 'float64') {
|
||||
throw new Error('Invalid input type');
|
||||
}
|
||||
};
|
||||
//# sourceMappingURL=softmax.js.map
|
||||
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/softmax.js.map
generated
vendored
Normal file
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/softmax.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
282
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/softmax.ts
generated
vendored
Normal file
282
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/softmax.ts
generated
vendored
Normal file
@@ -0,0 +1,282 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../../../attribute-with-cache-key';
|
||||
import {Graph} from '../../../graph';
|
||||
import {OperatorImplementation, OperatorInitialization} from '../../../operators';
|
||||
import {Tensor} from '../../../tensor';
|
||||
import {ShapeUtil} from '../../../util';
|
||||
import {getGlsl} from '../glsl-source';
|
||||
import {WebGLInferenceHandler} from '../inference-handler';
|
||||
import {ProgramInfo, TextureType} from '../types';
|
||||
|
||||
import {transpose, TransposeAttributes} from './transpose';
|
||||
|
||||
export interface SoftmaxAttributes extends AttributeWithCacheKey {
|
||||
readonly axis: number;
|
||||
}
|
||||
|
||||
const softmaxComputeMaxProgramMetadata = {
|
||||
name: 'SoftmaxComputeMax',
|
||||
inputNames: ['A'],
|
||||
inputTypes: [TextureType.unpacked],
|
||||
};
|
||||
|
||||
const softmaxComputeScaleProgramMetadata = {
|
||||
name: 'SoftmaxComputeScale',
|
||||
inputNames: ['A', 'Max'],
|
||||
inputTypes: [TextureType.unpacked, TextureType.unpacked],
|
||||
};
|
||||
|
||||
const softmaxProgramMetadata = {
|
||||
name: 'SoftMax',
|
||||
inputNames: ['A', 'Max', 'Norm'],
|
||||
inputTypes: [TextureType.unpacked, TextureType.unpacked, TextureType.unpacked],
|
||||
};
|
||||
|
||||
export const softmax: OperatorImplementation<SoftmaxAttributes> =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: SoftmaxAttributes): Tensor[] => {
|
||||
validateInputs(inputs);
|
||||
|
||||
const inputShape = inputs[0].dims.slice();
|
||||
const axis = ShapeUtil.normalizeAxis(attributes.axis, inputShape.length);
|
||||
const logicalRowCount = ShapeUtil.sizeToDimension(inputShape, axis);
|
||||
const featureCount = ShapeUtil.sizeFromDimension(inputShape, axis);
|
||||
|
||||
const output = computeSoftmax(inferenceHandler, inputs, attributes, logicalRowCount, featureCount);
|
||||
return output;
|
||||
};
|
||||
|
||||
export const parseSoftmaxAttributes: OperatorInitialization<SoftmaxAttributes> =
|
||||
(node: Graph.Node): SoftmaxAttributes => createAttributeWithCacheKey({axis: node.attributes.getInt('axis', 1)});
|
||||
|
||||
export const parseSoftmaxAttributesV13: OperatorInitialization<SoftmaxAttributes> =
|
||||
(node: Graph.Node): SoftmaxAttributes => createAttributeWithCacheKey({axis: node.attributes.getInt('axis', -1)});
|
||||
|
||||
// The "semantic" meaning of axis has changed in opset-13.
|
||||
// Please compare: https://github.com/onnx/onnx/blob/main/docs/Operators.md#Softmax
|
||||
// with https://github.com/onnx/onnx/blob/main/docs/Changelog.md#Softmax-11 for detailed explanations
|
||||
// To account for the opset-13 behavior, our plan will be to transpose the "axis" dim to the innermost dim
|
||||
// and perform softmax and then reverse the transpose. We can skip the transposing aspect if the axis is already
|
||||
// the innermost dim
|
||||
export const softmaxV13: OperatorImplementation<SoftmaxAttributes> =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: SoftmaxAttributes): Tensor[] => {
|
||||
validateInputs(inputs);
|
||||
|
||||
const inputShape = inputs[0].dims.slice();
|
||||
const axis = ShapeUtil.normalizeAxis(attributes.axis, inputShape.length);
|
||||
const rank = inputShape.length;
|
||||
|
||||
const isTransposeRequired = (axis !== rank - 1) ? true : false;
|
||||
const transposedInputShape: number[] = [];
|
||||
let perm: number[] = [];
|
||||
let transposedInputs: Tensor[] = [];
|
||||
let transposeAttribute: TransposeAttributes;
|
||||
|
||||
if (isTransposeRequired) {
|
||||
perm = Array.from({length: rank}).map((_, i) => i);
|
||||
|
||||
// swap the innermost dim with the dim corresponding to axis
|
||||
perm[axis] = rank - 1;
|
||||
perm[rank - 1] = axis;
|
||||
|
||||
perm.map(p => transposedInputShape.push(inputShape[p]));
|
||||
|
||||
transposeAttribute = createAttributeWithCacheKey({perm});
|
||||
transposedInputs = transpose(inferenceHandler, inputs, transposeAttribute);
|
||||
}
|
||||
|
||||
const logicalRowCount = isTransposeRequired ? ShapeUtil.sizeToDimension(transposedInputShape, rank - 1) :
|
||||
ShapeUtil.sizeToDimension(inputShape, rank - 1);
|
||||
const featureCount = isTransposeRequired ? ShapeUtil.sizeFromDimension(transposedInputShape, rank - 1) :
|
||||
ShapeUtil.sizeFromDimension(inputShape, rank - 1);
|
||||
|
||||
const output = computeSoftmax(
|
||||
inferenceHandler, isTransposeRequired ? transposedInputs : inputs, attributes, logicalRowCount, featureCount);
|
||||
|
||||
if (isTransposeRequired) {
|
||||
const reversedOutput = transpose(inferenceHandler, output, transposeAttribute!);
|
||||
return reversedOutput;
|
||||
} else {
|
||||
return output;
|
||||
}
|
||||
};
|
||||
|
||||
const computeSoftmax =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: SoftmaxAttributes, logicalRowCount: number,
|
||||
featureCount: number): Tensor[] => {
|
||||
const computeMaxProgramInfo =
|
||||
createComputeMaxProgramInfo(inferenceHandler, inputs[0], logicalRowCount, featureCount, [logicalRowCount]);
|
||||
const max = inferenceHandler.run(
|
||||
{...softmaxComputeMaxProgramMetadata, cacheHint: attributes.cacheKey, get: () => computeMaxProgramInfo},
|
||||
inputs);
|
||||
|
||||
const computeScaleProgramInfo = createComputScaleProgramInfo(
|
||||
inferenceHandler, inputs[0], logicalRowCount, featureCount, computeMaxProgramInfo.output.dims,
|
||||
[logicalRowCount]);
|
||||
const scale = inferenceHandler.run(
|
||||
{...softmaxComputeScaleProgramMetadata, cacheHint: attributes.cacheKey, get: () => computeScaleProgramInfo},
|
||||
[inputs[0], max]);
|
||||
|
||||
const softMaxProgramInfo = createSoftMaxProgramInfo(
|
||||
inferenceHandler, inputs[0], logicalRowCount, featureCount, computeMaxProgramInfo.output.dims,
|
||||
computeScaleProgramInfo.output.dims);
|
||||
const output = inferenceHandler.run(
|
||||
{...softmaxProgramMetadata, cacheHint: attributes.cacheKey, get: () => softMaxProgramInfo},
|
||||
[inputs[0], max, scale]);
|
||||
return [output];
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a texture that contains the maximum value of each of the 'N' rows
|
||||
*/
|
||||
const createComputeMaxProgramInfo =
|
||||
(inferenceHandler: WebGLInferenceHandler, input: Tensor, logicalRowCount: number, featureCount: number,
|
||||
outputShape: number[]): ProgramInfo => {
|
||||
const [textureWidth, textureHeight] =
|
||||
inferenceHandler.calculateTextureWidthAndHeight(input.dims, TextureType.unpacked);
|
||||
const rank = outputShape.length;
|
||||
|
||||
if (logicalRowCount < 1 || featureCount < 1) {
|
||||
throw new Error('Logical row count N and feature count D must be greater than or equal to 1');
|
||||
}
|
||||
|
||||
if (outputShape.length !== 1) {
|
||||
throw new Error('Dimensionality of the output should be 1');
|
||||
}
|
||||
|
||||
if (outputShape[0] !== logicalRowCount) {
|
||||
throw new Error('Shape of the output should be equal to logical row count');
|
||||
}
|
||||
|
||||
const glsl = getGlsl(inferenceHandler.session.backend.glContext.version);
|
||||
const shaderSource = `
|
||||
float process(int[${rank}] indices) {
|
||||
int logical_row_start_offset = indices[0] * ${featureCount};
|
||||
|
||||
float max = getColorAsFloat(${glsl.texture2D}(A, offsetToCoords(logical_row_start_offset, ${textureWidth},
|
||||
${textureHeight} )));
|
||||
for(int i=1; i<${featureCount}; ++i)
|
||||
{
|
||||
float current = getColorAsFloat(${glsl.texture2D}(A, offsetToCoords(logical_row_start_offset + i,
|
||||
${textureWidth}, ${textureHeight})));
|
||||
if(current > max)
|
||||
max = current;
|
||||
}
|
||||
|
||||
return max;
|
||||
}`;
|
||||
return {
|
||||
...softmaxComputeMaxProgramMetadata,
|
||||
output: {dims: outputShape, type: input.type, textureType: TextureType.unpacked},
|
||||
shaderSource
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a texture that contains the normalization factor for each of the 'N' rows
|
||||
*/
|
||||
const createComputScaleProgramInfo =
|
||||
(inferenceHandler: WebGLInferenceHandler, input: Tensor, logicalRowCount: number, featureCount: number,
|
||||
maxElementPerLogicalRow: readonly number[], outputShape: number[]): ProgramInfo => {
|
||||
const [textureWidth, textureHeight] =
|
||||
inferenceHandler.calculateTextureWidthAndHeight(input.dims, TextureType.unpacked);
|
||||
const rank = outputShape.length;
|
||||
|
||||
if (logicalRowCount < 1 || featureCount < 1) {
|
||||
throw new Error('Logical row count N and feature count D must be greater than or equal to 1');
|
||||
}
|
||||
|
||||
if (outputShape.length !== 1) {
|
||||
throw new Error('Dimensionality of the output should be 1');
|
||||
}
|
||||
|
||||
if (outputShape[0] !== logicalRowCount) {
|
||||
throw new Error('Shape of the output should be equal to logical row count');
|
||||
}
|
||||
|
||||
if (maxElementPerLogicalRow.length !== 1) {
|
||||
throw new Error('Dimensionality of the intermediate results should be 1');
|
||||
}
|
||||
|
||||
if (maxElementPerLogicalRow[0] !== logicalRowCount) {
|
||||
throw new Error('Shape of the intermediate results should be equal to logical row count');
|
||||
}
|
||||
|
||||
const glsl = getGlsl(inferenceHandler.session.backend.glContext.version);
|
||||
const shaderSource = `
|
||||
float process(int[${rank}] indices) {
|
||||
int logical_row_start_offset = indices[0] * ${featureCount};
|
||||
|
||||
float norm_factor = 0.0;
|
||||
float max = _Max(indices);
|
||||
for(int i=0; i<${featureCount}; ++i)
|
||||
{
|
||||
norm_factor += exp(getColorAsFloat(${glsl.texture2D}(A, offsetToCoords(logical_row_start_offset + i,
|
||||
${textureWidth}, ${textureHeight}))) - max);
|
||||
}
|
||||
|
||||
return norm_factor;
|
||||
}`;
|
||||
return {
|
||||
...softmaxComputeScaleProgramMetadata,
|
||||
output: {dims: outputShape, type: input.type, textureType: TextureType.unpacked},
|
||||
shaderSource
|
||||
};
|
||||
};
|
||||
|
||||
const createSoftMaxProgramInfo =
|
||||
(inferenceHandler: WebGLInferenceHandler, input: Tensor, logicalRowCount: number, featureCount: number,
|
||||
maxElementPerLogicalRow: readonly number[], normalizationPerLogicalRow: readonly number[]): ProgramInfo => {
|
||||
const [textureWidth, textureHeight] =
|
||||
inferenceHandler.calculateTextureWidthAndHeight(input.dims, TextureType.unpacked);
|
||||
const rank = input.dims.length;
|
||||
|
||||
if (logicalRowCount < 1 || featureCount < 1) {
|
||||
throw new Error('Logical row count N and feature count D must be greater than or equal to 1');
|
||||
}
|
||||
|
||||
if (maxElementPerLogicalRow.length !== 1 || normalizationPerLogicalRow.length !== 1) {
|
||||
throw new Error('Dimensionality of the intermediate results should be 1');
|
||||
}
|
||||
|
||||
if (maxElementPerLogicalRow[0] !== logicalRowCount || normalizationPerLogicalRow[0] !== logicalRowCount) {
|
||||
throw new Error('Shape of the intermediate results should be equal to logical row count');
|
||||
}
|
||||
|
||||
const shaderSource = `
|
||||
float process(int[${rank}] indices) {
|
||||
|
||||
// get offset of current logical tensor index from the 2-D texture coordinates (TexCoords)
|
||||
int offset = coordsToOffset(TexCoords, ${textureWidth}, ${textureHeight});
|
||||
|
||||
//determine the logical row for this index
|
||||
int logical_row_index[1];
|
||||
logical_row_index[0] = offset / ${featureCount};
|
||||
|
||||
float norm_factor = _Norm(logical_row_index);
|
||||
|
||||
// avoid possible division by 0
|
||||
// if norm_facor is 0, all elements are zero
|
||||
// if so, return 0
|
||||
if(norm_factor == 0.0)
|
||||
return 0.0;
|
||||
|
||||
return exp(_A(indices) - _Max(logical_row_index)) / norm_factor;
|
||||
}`;
|
||||
return {
|
||||
...softmaxProgramMetadata,
|
||||
output: {dims: input.dims, type: input.type, textureType: TextureType.unpacked},
|
||||
shaderSource
|
||||
};
|
||||
};
|
||||
|
||||
const validateInputs = (inputs: Tensor[]): void => {
|
||||
if (!inputs || inputs.length !== 1) {
|
||||
throw new Error('Softmax requires 1 input.');
|
||||
}
|
||||
|
||||
if (inputs[0].type !== 'float32' && inputs[0].type !== 'float64') {
|
||||
throw new Error('Invalid input type');
|
||||
}
|
||||
};
|
||||
59
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/split.js
generated
vendored
Normal file
59
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/split.js
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.parseSplitAttributes = exports.split = void 0;
|
||||
const attribute_with_cache_key_1 = require("../../../attribute-with-cache-key");
|
||||
const util_1 = require("../../../util");
|
||||
const types_1 = require("../types");
|
||||
const splitProgramMetadata = {
|
||||
name: 'Split',
|
||||
inputNames: ['A'],
|
||||
inputTypes: [types_1.TextureType.unpacked],
|
||||
};
|
||||
const split = (inferenceHandler, inputs, attributes) => {
|
||||
validateInputs(inputs);
|
||||
const axis = util_1.ShapeUtil.normalizeAxis(attributes.axis, inputs[0].dims.length);
|
||||
const count = getProgramCount(inferenceHandler, inputs, axis, attributes);
|
||||
const output = [];
|
||||
for (let i = 0; i < count; ++i) {
|
||||
output.push(inferenceHandler.run(Object.assign(Object.assign({}, splitProgramMetadata), { cacheHint: `${attributes.cacheKey};${i}`, get: () => createSplitProgramInfo(inferenceHandler, inputs[0], attributes, axis, i) }), inputs));
|
||||
}
|
||||
return output;
|
||||
};
|
||||
exports.split = split;
|
||||
const parseSplitAttributes = (node) => {
|
||||
const axis = node.attributes.getInt('axis', 0);
|
||||
const split = node.attributes.getInts('split', []);
|
||||
const numOutputs = node.outputs.length;
|
||||
return (0, attribute_with_cache_key_1.createAttributeWithCacheKey)({ axis, split, numOutputs });
|
||||
};
|
||||
exports.parseSplitAttributes = parseSplitAttributes;
|
||||
const getProgramCount = (inferenceHandler, inputs, axis, attributes) => {
|
||||
const [, offsets] = util_1.SplitUtil.splitShape(inputs[0].dims, axis, attributes.split, attributes.numOutputs);
|
||||
return offsets.length;
|
||||
};
|
||||
const createSplitProgramInfo = (inferenceHandler, input, attributes, axis, index) => {
|
||||
const [shapes, offsets] = util_1.SplitUtil.splitShape(input.dims, axis, attributes.split, attributes.numOutputs);
|
||||
const offset = offsets[index];
|
||||
const outputShape = shapes[index];
|
||||
const rank = outputShape.length;
|
||||
const shaderSource = `
|
||||
float process(int indices[${rank}]) {
|
||||
indices[${axis}] += ${offset};
|
||||
return _A(indices);
|
||||
}
|
||||
`;
|
||||
return Object.assign(Object.assign({}, splitProgramMetadata), { cacheHint: `${attributes.cacheKey}:${index}`, output: { dims: outputShape, type: input.type, textureType: types_1.TextureType.unpacked }, shaderSource });
|
||||
};
|
||||
const validateInputs = (inputs) => {
|
||||
if (!inputs || inputs.length !== 1) {
|
||||
throw new Error('Split requires one input.');
|
||||
}
|
||||
if (inputs[0].type !== 'int8' && inputs[0].type !== 'uint8' && inputs[0].type !== 'int16' &&
|
||||
inputs[0].type !== 'uint16' && inputs[0].type !== 'int32' && inputs[0].type !== 'uint32' &&
|
||||
inputs[0].type !== 'float32' && inputs[0].type !== 'float64' && inputs[0].type !== 'bool') {
|
||||
throw new Error('Invalid input type.');
|
||||
}
|
||||
};
|
||||
//# sourceMappingURL=split.js.map
|
||||
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/split.js.map
generated
vendored
Normal file
1
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/split.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"split.js","sourceRoot":"","sources":["split.ts"],"names":[],"mappings":"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"}
|
||||
88
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/split.ts
generated
vendored
Normal file
88
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/split.ts
generated
vendored
Normal file
@@ -0,0 +1,88 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
import {AttributeWithCacheKey, createAttributeWithCacheKey} from '../../../attribute-with-cache-key';
|
||||
import {Graph} from '../../../graph';
|
||||
import {OperatorImplementation, OperatorInitialization} from '../../../operators';
|
||||
import {Tensor} from '../../../tensor';
|
||||
import {ShapeUtil, SplitUtil} from '../../../util';
|
||||
import {WebGLInferenceHandler} from '../inference-handler';
|
||||
import {ProgramInfo, TextureType} from '../types';
|
||||
|
||||
export interface SplitAttributes extends AttributeWithCacheKey {
|
||||
readonly axis: number;
|
||||
readonly split: number[];
|
||||
readonly numOutputs: number;
|
||||
}
|
||||
|
||||
const splitProgramMetadata = {
|
||||
name: 'Split',
|
||||
inputNames: ['A'],
|
||||
inputTypes: [TextureType.unpacked],
|
||||
};
|
||||
|
||||
export const split: OperatorImplementation<SplitAttributes> =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], attributes: SplitAttributes): Tensor[] => {
|
||||
validateInputs(inputs);
|
||||
|
||||
const axis = ShapeUtil.normalizeAxis(attributes.axis, inputs[0].dims.length);
|
||||
const count = getProgramCount(inferenceHandler, inputs, axis, attributes);
|
||||
const output: Tensor[] = [];
|
||||
for (let i = 0; i < count; ++i) {
|
||||
output.push(inferenceHandler.run(
|
||||
{
|
||||
...splitProgramMetadata,
|
||||
cacheHint: `${attributes.cacheKey};${i}`,
|
||||
get: () => createSplitProgramInfo(inferenceHandler, inputs[0], attributes, axis, i)
|
||||
},
|
||||
inputs));
|
||||
}
|
||||
|
||||
return output;
|
||||
};
|
||||
|
||||
export const parseSplitAttributes: OperatorInitialization<SplitAttributes> = (node: Graph.Node): SplitAttributes => {
|
||||
const axis = node.attributes.getInt('axis', 0);
|
||||
const split = node.attributes.getInts('split', []);
|
||||
const numOutputs = node.outputs.length;
|
||||
return createAttributeWithCacheKey({axis, split, numOutputs});
|
||||
};
|
||||
|
||||
const getProgramCount =
|
||||
(inferenceHandler: WebGLInferenceHandler, inputs: Tensor[], axis: number, attributes: SplitAttributes): number => {
|
||||
const [, offsets] = SplitUtil.splitShape(inputs[0].dims, axis, attributes.split, attributes.numOutputs);
|
||||
return offsets.length;
|
||||
};
|
||||
|
||||
const createSplitProgramInfo =
|
||||
(inferenceHandler: WebGLInferenceHandler, input: Tensor, attributes: SplitAttributes, axis: number, index: number):
|
||||
ProgramInfo => {
|
||||
const [shapes, offsets] = SplitUtil.splitShape(input.dims, axis, attributes.split, attributes.numOutputs);
|
||||
const offset = offsets[index];
|
||||
const outputShape = shapes[index];
|
||||
const rank = outputShape.length;
|
||||
const shaderSource = `
|
||||
float process(int indices[${rank}]) {
|
||||
indices[${axis}] += ${offset};
|
||||
return _A(indices);
|
||||
}
|
||||
`;
|
||||
return {
|
||||
...splitProgramMetadata,
|
||||
cacheHint: `${attributes.cacheKey}:${index}`,
|
||||
output: {dims: outputShape, type: input.type, textureType: TextureType.unpacked},
|
||||
shaderSource
|
||||
};
|
||||
};
|
||||
|
||||
const validateInputs = (inputs: Tensor[]): void => {
|
||||
if (!inputs || inputs.length !== 1) {
|
||||
throw new Error('Split requires one input.');
|
||||
}
|
||||
|
||||
if (inputs[0].type !== 'int8' && inputs[0].type !== 'uint8' && inputs[0].type !== 'int16' &&
|
||||
inputs[0].type !== 'uint16' && inputs[0].type !== 'int32' && inputs[0].type !== 'uint32' &&
|
||||
inputs[0].type !== 'float32' && inputs[0].type !== 'float64' && inputs[0].type !== 'bool') {
|
||||
throw new Error('Invalid input type.');
|
||||
}
|
||||
};
|
||||
37
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/squeeze.js
generated
vendored
Normal file
37
node_modules/onnxruntime-web/lib/onnxjs/backends/webgl/ops/squeeze.js
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
"use strict";
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.parseSqueezeAttributes = exports.squeezeV13 = exports.squeeze = void 0;
|
||||
const util_1 = require("../../../util");
|
||||
const squeeze = (inferenceHandler, inputs, axes) => {
|
||||
validateInputs(inputs);
|
||||
const outputShape = util_1.ShapeUtil.squeezeShape(inputs[0].dims, axes);
|
||||
const output = inferenceHandler.reshapeUnpacked(inputs[0], outputShape);
|
||||
return [output];
|
||||
};
|
||||
exports.squeeze = squeeze;
|
||||
const squeezeV13 = (inferenceHandler, inputs) => {
|
||||
validateInputsV13(inputs);
|
||||
return (0, exports.squeeze)(inferenceHandler, [inputs[0]], Array.from(inputs[1].integerData));
|
||||
};
|
||||
exports.squeezeV13 = squeezeV13;
|
||||
const parseSqueezeAttributes = (node) => node.attributes.getInts('axes');
|
||||
exports.parseSqueezeAttributes = parseSqueezeAttributes;
|
||||
const validateInputs = (inputs) => {
|
||||
if (!inputs || inputs.length !== 1) {
|
||||
throw new Error('Squeeze requires 1 input.');
|
||||
}
|
||||
if (inputs[0].type === 'string') {
|
||||
throw new Error('invalid input tensor types.');
|
||||
}
|
||||
};
|
||||
const validateInputsV13 = (inputs) => {
|
||||
if (!inputs || inputs.length !== 2) {
|
||||
throw new Error('Squeeze requires 2 inputs.');
|
||||
}
|
||||
if (inputs[1].type !== 'int32') {
|
||||
throw new Error('Invalid input type.');
|
||||
}
|
||||
};
|
||||
//# sourceMappingURL=squeeze.js.map
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user