mirror of
https://github.com/saymrwulf/onnxruntime.git
synced 2026-05-18 21:21:17 +00:00
* migrated changes to support running super resolution model using ortweb * reverted benchmarking tool related changes which will be in a separate pr * added kernel tests to op and node tests * minor change to the order of variables * added one more unit test for packed matmul
148 lines
4.7 KiB
TypeScript
148 lines
4.7 KiB
TypeScript
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// Licensed under the MIT License.
|
|
|
|
import {WebGLContext} from '../../../../lib/onnxjs/backends/webgl/webgl-context';
|
|
|
|
export function createAscendingArray(size: number): Float32Array {
|
|
return new Float32Array(Array.from({length: size}, (v, i) => (i + 1)));
|
|
}
|
|
|
|
// Returns an array by injecting 3 zeros after every element in the input array to be used for creating unpacked
|
|
// texture.
|
|
export function generateArrayForUnpackedTexture(input: Float32Array): Float32Array {
|
|
const output = new Float32Array(input.length * 4);
|
|
for (let i = 0; i < (input.length * 4); i += 4) {
|
|
output[i] = input[i / 4];
|
|
}
|
|
return output;
|
|
}
|
|
|
|
// create a webgl texture and fill it with the array content
|
|
export function createTextureFromArray(
|
|
glContext: WebGLContext, dataArray: Float32Array, type: GLenum, width: number, height: number): WebGLTexture {
|
|
const gl = glContext.gl;
|
|
|
|
// create the texture
|
|
const texture = gl.createTexture();
|
|
if (!texture) {
|
|
throw new Error('failed to create texture');
|
|
}
|
|
// bind the texture so the following methods effect this texture.
|
|
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
if (glContext.version === 2) {
|
|
const webgl2Gl = gl as WebGL2RenderingContext;
|
|
gl.texImage2D(webgl2Gl.TEXTURE_2D, 0, webgl2Gl.RGBA32F, width, height, 0, webgl2Gl.RGBA, webgl2Gl.FLOAT, dataArray);
|
|
} else {
|
|
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.FLOAT, dataArray);
|
|
}
|
|
|
|
glContext.checkError();
|
|
return texture;
|
|
}
|
|
|
|
// create a cpu array and download GPU texture data to this array
|
|
export function createArrayFromTexture(
|
|
gl: WebGLRenderingContext, texture: WebGLTexture, width: number, height: number): Float32Array {
|
|
const resultDataBuffer = new Float32Array(width * height * 4);
|
|
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
gl.framebufferTexture2D(
|
|
gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture,
|
|
0); // 0, we aren't using MIPMAPs
|
|
gl.readPixels(0, 0, width, height, gl.RGBA, gl.FLOAT, resultDataBuffer);
|
|
return resultDataBuffer;
|
|
}
|
|
|
|
export function getExpectedElementCount(inputShape: number[], isPacked = true): number {
|
|
const rank = inputShape.length;
|
|
|
|
if (isPacked) {
|
|
// scalar
|
|
if (rank === 0) {
|
|
return 4;
|
|
}
|
|
|
|
// 1D tensor
|
|
if (rank === 1) {
|
|
if (inputShape[0] % 2) {
|
|
return (inputShape[0] + 1) * 2;
|
|
} else {
|
|
return inputShape[0] * 2;
|
|
}
|
|
}
|
|
|
|
// process width
|
|
let inputWidth = inputShape[rank - 2] % 2 ? inputShape[rank - 2] + 1 : inputShape[rank - 2];
|
|
if (rank > 2) {
|
|
for (let i = 0; i < rank - 2; ++i) {
|
|
inputWidth *= inputShape[i];
|
|
}
|
|
}
|
|
// process height
|
|
let inputHeight = inputShape[rank - 1];
|
|
if (inputHeight % 2) {
|
|
inputHeight++;
|
|
}
|
|
return inputWidth * inputHeight;
|
|
} else {
|
|
let totalCount = 1;
|
|
for (let i = 0; i < rank; i++) {
|
|
totalCount *= inputShape[i];
|
|
}
|
|
return totalCount;
|
|
}
|
|
}
|
|
|
|
export function generateExpected(inputArray: Float32Array, inputShape: number[]): Float32Array {
|
|
if (inputShape.length === 0) {
|
|
const result = new Float32Array(4);
|
|
result[0] = inputArray[0];
|
|
return result;
|
|
}
|
|
const rank = inputShape.length;
|
|
|
|
const inputHeight = rank === 1 ? 1 : inputShape[rank - 2];
|
|
const inputWidth = inputShape[rank - 1];
|
|
const paddedW = inputWidth % 2 ? inputWidth + 1 : inputWidth;
|
|
const paddedH = inputHeight % 2 ? inputHeight + 1 : inputHeight;
|
|
|
|
let B = 1;
|
|
if (rank > 2) {
|
|
for (let i = 0; i < rank - 2; ++i) {
|
|
B *= inputShape[i];
|
|
}
|
|
}
|
|
|
|
const result = new Float32Array(B * paddedW * paddedH);
|
|
let ii = 0;
|
|
for (let b = 0; b < B; ++b) {
|
|
for (let j = 0; j < paddedH; j += 2) {
|
|
for (let i = 0; i < paddedW; i += 2) {
|
|
const index = j * inputWidth + i + b * (inputHeight * inputWidth);
|
|
result[ii++] = inputArray[index];
|
|
|
|
if (i + 1 < inputWidth) {
|
|
result[ii++] = inputArray[index + 1];
|
|
} else {
|
|
result[ii++] = 0;
|
|
}
|
|
|
|
if ((j + 1) < inputHeight) {
|
|
result[ii++] = inputArray[(j + 1) * inputWidth + i + b * (inputHeight * inputWidth)];
|
|
} else {
|
|
result[ii++] = 0;
|
|
}
|
|
|
|
if (i + 1 < inputWidth && j + 1 < inputHeight) {
|
|
result[ii++] = inputArray[(j + 1) * inputWidth + i + 1 + b * (inputHeight * inputWidth)];
|
|
} else {
|
|
result[ii++] = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|