onnxruntime/js/web/test/unittests/backends/webgl/test-utils.ts
Tixxx ea1a4f8fb5
[JS]support running super resolution model using ortweb (#7677)
* 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
2021-05-25 17:43:43 -07:00

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;
}