Skip to content
This repository was archived by the owner on Aug 15, 2019. It is now read-only.

add experimental webgl support for RN platform #1844

Merged
merged 25 commits into from
Jul 29, 2019
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 2 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,5 @@ rollup.config.js
tsconfig.json
.yalc/
yalc.lock
tfjs-react-native/
tfjs-backend-nodegl/
10 changes: 5 additions & 5 deletions src/backends/webgl/clip_gpu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ export class ClipProgram implements GPGPUProgram {
constructor(aShape: number[]) {
this.outputShape = aShape;
this.userCode = `
uniform float min;
uniform float max;
uniform float minVal;
uniform float maxVal;

void main() {
float value = getAAtOutCoords();
Expand All @@ -40,16 +40,16 @@ export class ClipProgram implements GPGPUProgram {
return;
}

setOutput(clamp(value, min, max));
setOutput(clamp(value, minVal, maxVal));
}
`;
}

getCustomSetupFunc(min: number, max: number) {
return (gpgpu: GPGPUContext, webGLProgram: WebGLProgram) => {
if (this.minLoc == null) {
this.minLoc = gpgpu.getUniformLocationNoThrow(webGLProgram, 'min');
this.maxLoc = gpgpu.getUniformLocationNoThrow(webGLProgram, 'max');
this.minLoc = gpgpu.getUniformLocationNoThrow(webGLProgram, 'minVal');
this.maxLoc = gpgpu.getUniformLocationNoThrow(webGLProgram, 'maxVal');
}
gpgpu.gl.uniform1f(this.minLoc, min);
gpgpu.gl.uniform1f(this.maxLoc, max);
Expand Down
10 changes: 5 additions & 5 deletions src/backends/webgl/clip_packed_gpu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ export class ClipPackedProgram implements GPGPUProgram {
constructor(aShape: number[]) {
this.outputShape = aShape;
this.userCode = `
uniform float min;
uniform float max;
uniform float minVal;
uniform float maxVal;

void main() {
vec4 value = getAAtOutCoords();
Expand All @@ -42,16 +42,16 @@ export class ClipPackedProgram implements GPGPUProgram {
return;
}

setOutput(clamp(value, vec4(min), vec4(max)));
setOutput(clamp(value, vec4(minVal), vec4(maxVal)));
}
`;
}

getCustomSetupFunc(min: number, max: number) {
return (gpgpu: GPGPUContext, webGLProgram: WebGLProgram) => {
if (this.minLoc == null) {
this.minLoc = gpgpu.getUniformLocationNoThrow(webGLProgram, 'min');
this.maxLoc = gpgpu.getUniformLocationNoThrow(webGLProgram, 'max');
this.minLoc = gpgpu.getUniformLocationNoThrow(webGLProgram, 'minVal');
this.maxLoc = gpgpu.getUniformLocationNoThrow(webGLProgram, 'maxVal');
}
gpgpu.gl.uniform1f(this.minLoc, min);
gpgpu.gl.uniform1f(this.maxLoc, max);
Expand Down
6 changes: 3 additions & 3 deletions src/backends/webgl/glsl_version.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ export function getGlslDifferences(): GLSL {
return (val > 0. || val < 0. || val == 0.) ? false : true;
}
`;
defineSpecialInf = `
const float INFINITY = uintBitsToFloat(uint(0x7f800000));
`;
// In webgl 2 we do not need to specify a custom isinf so there is no
// need for a special INFINITY constant.
defineSpecialInf = ``;
defineRound = `
#define round(value) newRound(value)
int newRound(float value) {
Expand Down
17 changes: 13 additions & 4 deletions src/backends/webgl/gpgpu_context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ import * as util from '../../util';

import {getWebGLContext, setWebGLContext} from './canvas_util';
import * as gpgpu_util from './gpgpu_util';
import {TextureConfig} from './gpgpu_util';
import * as tex_util from './tex_util';
import {TextureConfig} from './tex_util';
import {WebGL1DisjointQueryTimerExtension, WebGL2DisjointQueryTimerExtension} from './webgl_types';
import * as webgl_util from './webgl_util';

Expand Down Expand Up @@ -70,16 +70,25 @@ export class GPGPUContext {
this.gl.getExtension('EXT_color_buffer_half_float');
}
} else {
this.colorBufferFloatExtension = webgl_util.getExtensionOrThrow(
this.gl, this.debug, 'EXT_color_buffer_float');
const COLOR_BUFFER_FLOAT = 'EXT_color_buffer_float';
const COLOR_BUFFER_HALF_FLOAT = 'EXT_color_buffer_half_float';
if (webgl_util.hasExtension(this.gl, COLOR_BUFFER_FLOAT)) {
this.colorBufferFloatExtension =
this.gl.getExtension(COLOR_BUFFER_FLOAT);
} else if (webgl_util.hasExtension(this.gl, COLOR_BUFFER_HALF_FLOAT)) {
this.colorBufferHalfFloatExtension =
this.gl.getExtension(COLOR_BUFFER_HALF_FLOAT);
} else {
throw new Error('GL context does not support color renderable floats');
}
}

this.vertexBuffer = gpgpu_util.createVertexBuffer(this.gl, this.debug);
this.indexBuffer = gpgpu_util.createIndexBuffer(this.gl, this.debug);
this.framebuffer = webgl_util.createFramebuffer(this.gl, this.debug);

this.textureConfig =
gpgpu_util.getTextureConfig(this.gl, this.textureHalfFloatExtension);
tex_util.getTextureConfig(this.gl, this.textureHalfFloatExtension);
}

private get debug(): boolean {
Expand Down
72 changes: 1 addition & 71 deletions src/backends/webgl/gpgpu_util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,29 +15,13 @@
* =============================================================================
*/

import {ENV} from '../../environment';
import {PixelData, TypedArray} from '../../types';

import {getGlslDifferences} from './glsl_version';
import * as tex_util from './tex_util';
import {TextureConfig} from './tex_util';
import * as webgl_util from './webgl_util';

export interface TextureConfig {
internalFormatFloat: number;
textureFormatFloat: number;
internalFormatPackedHalfFloat: number;
internalFormatHalfFloat: number;
internalFormatPackedFloat: number;

// The format to use during a gl.readPixels call.
downloadTextureFormat: number;
// How many channels need to be unpacked after a gl.readPixels call.
downloadUnpackNumChannels: number;

defaultNumChannels: number;
textureTypeHalfFloat: number;
}

export function createVertexShader(
gl: WebGLRenderingContext, debug: boolean): WebGLShader {
const glsl = getGlslDifferences();
Expand Down Expand Up @@ -69,60 +53,6 @@ export function createIndexBuffer(
return webgl_util.createStaticIndexBuffer(gl, debug, triangleVertexIndices);
}

export function getTextureConfig(
// tslint:disable-next-line:no-any
gl: WebGLRenderingContext, textureHalfFloatExtension?: any): TextureConfig {
// tslint:disable-next-line:no-any
const glany = gl as any;

let internalFormatFloat: number;
let internalFormatHalfFloat: number;
let internalFormatPackedHalfFloat: number;
let internalFormatPackedFloat: number;
let textureFormatFloat: number;

let downloadTextureFormat: number;
let downloadUnpackNumChannels: number;

let defaultNumChannels: number;
let textureTypeHalfFloat: number;

if (ENV.getNumber('WEBGL_VERSION') === 2) {
internalFormatFloat = glany.R32F;
internalFormatHalfFloat = glany.R16F;
internalFormatPackedHalfFloat = glany.RGBA16F;
internalFormatPackedFloat = glany.RGBA32F;
textureFormatFloat = glany.RED;
downloadUnpackNumChannels = 4;
defaultNumChannels = 1;
textureTypeHalfFloat = glany.HALF_FLOAT;
} else {
internalFormatFloat = gl.RGBA;
internalFormatHalfFloat = gl.RGBA;
internalFormatPackedHalfFloat = gl.RGBA;
internalFormatPackedFloat = glany.RGBA;
textureFormatFloat = gl.RGBA;
downloadUnpackNumChannels = 4;
defaultNumChannels = 4;
textureTypeHalfFloat = textureHalfFloatExtension != null ?
textureHalfFloatExtension.HALF_FLOAT_OES :
null;
}
downloadTextureFormat = gl.RGBA;

return {
internalFormatFloat,
internalFormatHalfFloat,
internalFormatPackedHalfFloat,
internalFormatPackedFloat,
textureFormatFloat,
downloadTextureFormat,
downloadUnpackNumChannels,
defaultNumChannels,
textureTypeHalfFloat
};
}

function createAndConfigureTexture(
gl: WebGLRenderingContext, debug: boolean, width: number, height: number,
internalFormat: number, textureFormat: number,
Expand Down
9 changes: 5 additions & 4 deletions src/backends/webgl/gpgpu_util_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {describeWithFlags} from '../../jasmine_util';
import {WEBGL_ENVS} from './backend_webgl_test_registry';
import {GPGPUContext} from './gpgpu_context';
import * as gpgpu_util from './gpgpu_util';
import * as tex_util from './tex_util';

describeWithFlags('gpgpu_util createWebGLContext', WEBGL_ENVS, () => {
let gpgpu: GPGPUContext;
Expand Down Expand Up @@ -59,7 +60,7 @@ describeWithFlags('gpgpu_util createWebGLContext', WEBGL_ENVS, () => {
describeWithFlags('gpgpu_util createFloat32MatrixTexture', WEBGL_ENVS, () => {
it('sets the TEXTURE_WRAP S+T parameters to CLAMP_TO_EDGE', () => {
const gpgpu = new GPGPUContext();
const textureConfig = gpgpu_util.getTextureConfig(gpgpu.gl);
const textureConfig = tex_util.getTextureConfig(gpgpu.gl);
const debug = false;
const tex = gpgpu_util.createFloat32MatrixTexture(
gpgpu.gl, debug, 32, 32, textureConfig);
Expand All @@ -77,7 +78,7 @@ describeWithFlags('gpgpu_util createFloat32MatrixTexture', WEBGL_ENVS, () => {

it('sets the TEXTURE_[MIN|MAG]_FILTER parameters to NEAREST', () => {
const gpgpu = new GPGPUContext();
const textureConfig = gpgpu_util.getTextureConfig(gpgpu.gl);
const textureConfig = tex_util.getTextureConfig(gpgpu.gl);
const debug = false;
const tex = gpgpu_util.createFloat32MatrixTexture(
gpgpu.gl, debug, 32, 32, textureConfig);
Expand All @@ -97,7 +98,7 @@ describeWithFlags('gpgpu_util createFloat32MatrixTexture', WEBGL_ENVS, () => {
describeWithFlags('gpgpu_util createPackedMatrixTexture', WEBGL_ENVS, () => {
it('sets the TEXTURE_WRAP S+T parameters to CLAMP_TO_EDGE', () => {
const gpgpu = new GPGPUContext();
const textureConfig = gpgpu_util.getTextureConfig(gpgpu.gl);
const textureConfig = tex_util.getTextureConfig(gpgpu.gl);
const debug = false;
const tex = gpgpu_util.createPackedMatrixTexture(
gpgpu.gl, debug, 32, 32, textureConfig);
Expand All @@ -115,7 +116,7 @@ describeWithFlags('gpgpu_util createPackedMatrixTexture', WEBGL_ENVS, () => {

it('sets the TEXTURE_[MIN|MAG]_FILTER parameters to NEAREST', () => {
const gpgpu = new GPGPUContext();
const textureConfig = gpgpu_util.getTextureConfig(gpgpu.gl);
const textureConfig = tex_util.getTextureConfig(gpgpu.gl);
const debug = false;
const tex = gpgpu_util.createPackedMatrixTexture(
gpgpu.gl, debug, 32, 32, textureConfig);
Expand Down
76 changes: 76 additions & 0 deletions src/backends/webgl/tex_util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
* =============================================================================
*/

import {ENV} from '../../environment';
import {DataId, Tensor} from '../../tensor';
import {BackendValues, DataType} from '../../types';
import * as util from '../../util';
Expand Down Expand Up @@ -121,3 +122,78 @@ export function getPackedRGBAArraySizeFromMatrixShape(
const [w, h] = getPackedMatrixTextureShapeWidthHeight(rows, columns);
return w * h * 4;
}

export interface TextureConfig {
internalFormatFloat: number;
textureFormatFloat: number;
internalFormatPackedHalfFloat: number;
internalFormatHalfFloat: number;
internalFormatPackedFloat: number;

// The format to use during a gl.readPixels call.
downloadTextureFormat: number;
// How many channels need to be unpacked after a gl.readPixels call.
downloadUnpackNumChannels: number;

defaultNumChannels: number;
textureTypeHalfFloat: number;
textureTypeFloat: number;
}

export function getTextureConfig(
// tslint:disable-next-line:no-any
gl: WebGLRenderingContext, textureHalfFloatExtension?: any): TextureConfig {
// tslint:disable-next-line:no-any
const glany = gl as any;

let internalFormatFloat: number;
let internalFormatHalfFloat: number;
let internalFormatPackedHalfFloat: number;
let internalFormatPackedFloat: number;
let textureFormatFloat: number;

let downloadTextureFormat: number;
let downloadUnpackNumChannels: number;

let defaultNumChannels: number;
let textureTypeHalfFloat: number;
let textureTypeFloat: number;

if (ENV.getNumber('WEBGL_VERSION') === 2) {
internalFormatFloat = glany.R32F;
internalFormatHalfFloat = glany.R16F;
internalFormatPackedHalfFloat = glany.RGBA16F;
internalFormatPackedFloat = glany.RGBA32F;
textureFormatFloat = glany.RED;
downloadUnpackNumChannels = 4;
defaultNumChannels = 1;
textureTypeHalfFloat = glany.HALF_FLOAT;
textureTypeFloat = glany.FLOAT;
} else {
internalFormatFloat = gl.RGBA;
internalFormatHalfFloat = gl.RGBA;
internalFormatPackedHalfFloat = gl.RGBA;
internalFormatPackedFloat = glany.RGBA;
textureFormatFloat = gl.RGBA;
downloadUnpackNumChannels = 4;
defaultNumChannels = 4;
textureTypeHalfFloat = textureHalfFloatExtension != null ?
textureHalfFloatExtension.HALF_FLOAT_OES :
null;
textureTypeFloat = gl.FLOAT;
}
downloadTextureFormat = gl.RGBA;

return {
internalFormatFloat,
internalFormatHalfFloat,
internalFormatPackedHalfFloat,
internalFormatPackedFloat,
textureFormatFloat,
downloadTextureFormat,
downloadUnpackNumChannels,
defaultNumChannels,
textureTypeHalfFloat,
textureTypeFloat
};
}
Loading