Skip to content
This repository has been archived by the owner on Nov 16, 2023. It is now read-only.

webgl: fix issues on Android devices #149

Merged
merged 16 commits into from
May 31, 2019
Merged
Show file tree
Hide file tree
Changes from 14 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,23 @@ module.exports = function(config) {
os: 'ios',
os_version: '10.3',
},

// Android
//
BS_ANDROID_9_Pixel_3: {
base: 'BrowserStack',
device: 'Google Pixel 3',
real_mobile: true,
os: 'android',
os_version: '9.0',
},
BS_ANDROID_7_1_Galaxy_Note_8: {
base: 'BrowserStack',
device: 'Samsung Galaxy Note 8',
real_mobile: true,
os: 'android',
os_version: '7.1',
},
}
});
};
4 changes: 4 additions & 0 deletions lib/api/onnx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ export declare namespace Backend {
* set or get the WebGL Context ID (webgl or webgl2)
*/
contextId?: 'webgl'|'webgl2';
/**
* set or get the maximum batch size for matmul. 0 means to disable batching.
*/
matmulMaxBatchSize?: number;
}
/**
* set options for the WebAssembly backend
Expand Down
6 changes: 3 additions & 3 deletions lib/backends/backend-webgl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,13 @@ export class WebGLBackend implements Backend, WebGLOptions {
disabled?: boolean;
glContext: WebGLContext;
contextId?: 'webgl'|'webgl2';
forceUint8Reads = false;
matmulMaxBatchSize?: number;

initialize(): boolean {
try {
this.glContext = createWebGLContext(this.contextId);
if (!this.glContext.floatDownloadEnabled) {
this.forceUint8Reads = true;
if (typeof this.matmulMaxBatchSize !== 'number') {
this.matmulMaxBatchSize = 16;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this because this was the default value previously ? I mean there is no data to choose this value right ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is because it's the previous default value.

}
Logger.verbose('WebGLBackend', `Created WebGLContext: ${typeof this.glContext}`);
return true;
Expand Down
22 changes: 5 additions & 17 deletions lib/backends/webgl/glsl-coordinate-lib.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the MIT license.

import {GlslContext, GlslLib, GlslLibRoutine} from './glsl-definitions';
import {getGlsl} from './glsl-source';

/**
* GLSL Library responsible for data types and routines for manipulating
Expand Down Expand Up @@ -66,13 +67,6 @@ export class CoordsGlslLib extends GlslLib {
const xScale = output.width;
const yScale = output.height;

const offsetFromBlocks = (this.context.programInfo.blockSize) ? `
int offsetFromBlocks(vec2 coords, int blockWidth, int blockHeight,
int blockXOffset, int blockYOffset, int totalWidth) {
coords = TexCoords * vec2(blockWidth, blockHeight) + vec2(blockXOffset, blockYOffset);
return int(coords.t) * totalWidth + int(coords.s);
}` :
'';
const stridesBlock = [];
for (let i = 0; i < rank - 1; ++i) {
stridesBlock.push(`
Expand All @@ -82,15 +76,9 @@ export class CoordsGlslLib extends GlslLib {
}
stridesBlock.push(`
c[${rank - 1}] = offset;`);
const offsetLine = (this.context.programInfo.blockSize) ? `
int offset = offsetFromBlocks(TexCoords, blockWidth, blockHeight, blockXOffset, blockYOffset, ${xScale});` :

`
int offset = coordsToOffset(texCoords, ${xScale}, ${yScale});`;
const body = `
${offsetFromBlocks}
void toVec(vec2 texCoords, out int c[${rank}]) {
${offsetLine}
int offset = coordsToOffset(texCoords, ${xScale}, ${yScale});
${stridesBlock.join('')}
}
void toVec(int offset, out int c[${rank}]) {
Expand All @@ -108,8 +96,7 @@ export class CoordsGlslLib extends GlslLib {
protected valueFrom(): {[name: string]: GlslLibRoutine} {
const programInfo = this.context.programInfo;
const result: {[name: string]: GlslLibRoutine} = {};
this.context.uniformInfo.filter(ui => ui.type === 'sampler2D').forEach((ui, i) => {
const name = ui.name;
this.context.programInfo.samplers.forEach((name, i) => {
const layout = programInfo.inputLayouts[i];
const shape = layout.shape;
const rank = shape.length;
Expand Down Expand Up @@ -137,11 +124,12 @@ export class CoordsGlslLib extends GlslLib {
if (transpose) {
name = name + '_T';
}
const glsl = getGlsl(this.context.glContext.version);
return `
float ${name}(int m[${rank}]) {
int offset = indicesToOffset${name}(m);
vec2 coords = offsetToCoords(offset, ${width}, ${height});
float value = getColorAsFloat(texture2D(${varName}, coords));
float value = getColorAsFloat(${glsl.texture2D}(${varName}, coords));
return value;
}
`;
Expand Down
6 changes: 2 additions & 4 deletions lib/backends/webgl/glsl-definitions.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

import {ProgramInfo, VariableInfo} from './types';
import {ProgramInfo} from './types';
import {WebGLContext} from './webgl-context';

export enum FunctionType {
Expand All @@ -20,9 +20,7 @@ export interface GlslPositionalFunction extends GlslFunction<FunctionType.Positi
}

export class GlslContext {
constructor(
public glContext: WebGLContext, public programInfo: ProgramInfo, public attribInfo: VariableInfo[],
public uniformInfo: VariableInfo[]) {}
constructor(public glContext: WebGLContext, public programInfo: ProgramInfo) {}
}
export abstract class GlslLib {
constructor(public context: GlslContext) {}
Expand Down
4 changes: 3 additions & 1 deletion lib/backends/webgl/glsl-fragcolor-lib.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the MIT license.

import {GlslContext, GlslLib, GlslLibRoutine} from './glsl-definitions';
import {getGlsl} from './glsl-source';

/**
* This GLSL library handles routines around reading a texlet and writing to it
Expand All @@ -19,11 +20,12 @@ export class FragColorGlslLib extends GlslLib {
return {};
}
protected setFragColor(): {[name: string]: GlslLibRoutine} {
const glsl = getGlsl(this.context.glContext.version);
return {
setFragColor: new GlslLibRoutine(
`
void setFragColor(float value) {
gl_FragColor = encode(value);
${glsl.output} = encode(value);
}
`,
['encoding.encode'])
Expand Down
93 changes: 44 additions & 49 deletions lib/backends/webgl/glsl-function-inliner.ts
Original file line number Diff line number Diff line change
@@ -1,59 +1,54 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

const INLINE_FUNC_DEF_REGEX: RegExp =
/@inline[\s\n\r]+(\w+)[\s\n\r]+([0-9a-zA-Z_]+)\s*\(([^)]*)\)\s*{(([^}]|[\n\r])*)}/gm;
const FUNC_CALL_REGEX = '(\\w+)?\\s+([_0-9a-zA-Z]+)\\s+=\\s+__FUNC__\\((.*)\\)\\s*;';
/**
* GLSL preprocessor class responsible for resolving @inline directives
* GLSL preprocessor responsible for resolving @inline directives
*/
export class GlslFunctionInliner {
// tslint:disable-next-line:variable-name
static readonly InlineFuncDefRegex: RegExp =
/@inline[\s\n\r]+(\w+)[\s\n\r]+([0-9a-zA-Z_]+)\s*\(([^)]*)\)\s*{(([^}]|[\n\r])*)}/gm;
// tslint:disable-next-line:variable-name
static readonly FuncCallRegex = '(\\w+)?\\s+([_0-9a-zA-Z]+)\\s+=\\s+__FUNC__\\((.*)\\)\\s*;';

inline(script: string) {
const inlineDefs: {[name: string]: {params: Array<{type: string, name: string}|null>, body: string}} = {};
let match;
while ((match = GlslFunctionInliner.InlineFuncDefRegex.exec(script)) !== null) {
const params = match[3]
.split(',')
.map(s => {
const tokens = s.trim().split(' ');
if (tokens && tokens.length === 2) {
return {type: tokens[0], name: tokens[1]};
}
return null;
})
.filter(v => v !== null);
inlineDefs[match[2]] = {params, body: match[4]};
}
for (const name in inlineDefs) {
const regexString = GlslFunctionInliner.FuncCallRegex.replace('__FUNC__', name);
const regex = new RegExp(regexString, 'gm');
while ((match = regex.exec(script)) !== null) {
const type = match[1];
const variable = match[2];
const params = match[3].split(',');
const declLine = (type) ? `${type} ${variable};` : '';
let newBody: string = inlineDefs[name].body;
let paramRedecLine = '';
inlineDefs[name].params.forEach((v, i) => {
if (v) {
paramRedecLine += `${v.type} ${v.name} = ${params[i]};\n`;
}
});
newBody = `${paramRedecLine}\n ${newBody}`;
newBody = newBody.replace('return', `${variable} = `);
const replacement = `
${declLine}
{
${newBody}
export function replaceInlines(script: string): string {
const inlineDefs: {[name: string]: {params: Array<{type: string, name: string}|null>, body: string}} = {};
let match;
while ((match = INLINE_FUNC_DEF_REGEX.exec(script)) !== null) {
const params = match[3]
.split(',')
.map(s => {
const tokens = s.trim().split(' ');
if (tokens && tokens.length === 2) {
return {type: tokens[0], name: tokens[1]};
}
return null;
})
.filter(v => v !== null);
inlineDefs[match[2]] = {params, body: match[4]};
}
for (const name in inlineDefs) {
const regexString = FUNC_CALL_REGEX.replace('__FUNC__', name);
const regex = new RegExp(regexString, 'gm');
while ((match = regex.exec(script)) !== null) {
const type = match[1];
const variable = match[2];
const params = match[3].split(',');
const declLine = (type) ? `${type} ${variable};` : '';
let newBody: string = inlineDefs[name].body;
let paramRedecLine = '';
inlineDefs[name].params.forEach((v, i) => {
if (v) {
paramRedecLine += `${v.type} ${v.name} = ${params[i]};\n`;
}
`;
script = script.replace(match[0], replacement);
});
newBody = `${paramRedecLine}\n ${newBody}`;
newBody = newBody.replace('return', `${variable} = `);
const replacement = `
${declLine}
{
${newBody}
}
`;
script = script.replace(match[0], replacement);
}
script = script.replace(GlslFunctionInliner.InlineFuncDefRegex, '');
return script;
}
script = script.replace(INLINE_FUNC_DEF_REGEX, '');
return script;
}
Loading