UNPKG

@tensorflow/tfjs-core

Version:

Hardware-accelerated JavaScript library for machine intelligence

282 lines 15.3 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [0, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; Object.defineProperty(exports, "__esModule", { value: true }); var environment_1 = require("../../environment"); var tex_util = require("./tex_util"); var webgl_util = require("./webgl_util"); function getWebGLContextAttributes() { return { alpha: false, antialias: false, premultipliedAlpha: false, preserveDrawingBuffer: false, depth: false, stencil: false, failIfMajorPerformanceCaveat: true }; } exports.getWebGLContextAttributes = getWebGLContextAttributes; function createWebGLContext(canvas) { var attributes = getWebGLContextAttributes(); var gl; if (canvas != null) { gl = webgl_util.createWebGLRenderingContextFromCanvas(canvas, attributes); } else { gl = webgl_util.createWebGLRenderingContext(attributes); } webgl_util.callAndCheck(gl, function () { return gl.disable(gl.DEPTH_TEST); }); webgl_util.callAndCheck(gl, function () { return gl.disable(gl.STENCIL_TEST); }); webgl_util.callAndCheck(gl, function () { return gl.disable(gl.BLEND); }); webgl_util.callAndCheck(gl, function () { return gl.disable(gl.DITHER); }); webgl_util.callAndCheck(gl, function () { return gl.disable(gl.POLYGON_OFFSET_FILL); }); webgl_util.callAndCheck(gl, function () { return gl.disable(gl.SAMPLE_COVERAGE); }); webgl_util.callAndCheck(gl, function () { return gl.enable(gl.SCISSOR_TEST); }); webgl_util.callAndCheck(gl, function () { return gl.enable(gl.CULL_FACE); }); webgl_util.callAndCheck(gl, function () { return gl.cullFace(gl.BACK); }); return gl; } exports.createWebGLContext = createWebGLContext; function createVertexShader(gl) { var vertexShaderSource = "\n precision highp float;\n attribute vec3 clipSpacePos;\n attribute vec2 uv;\n varying vec2 resultUV;\n\n void main() {\n gl_Position = vec4(clipSpacePos, 1);\n resultUV = uv;\n }"; return webgl_util.createVertexShader(gl, vertexShaderSource); } exports.createVertexShader = createVertexShader; function createVertexBuffer(gl) { var vertexArray = new Float32Array([-1, 1, 0, 0, 1, -1, -1, 0, 0, 0, 1, 1, 0, 1, 1, 1, -1, 0, 1, 0]); return webgl_util.createStaticVertexBuffer(gl, vertexArray); } exports.createVertexBuffer = createVertexBuffer; function createIndexBuffer(gl) { var triangleVertexIndices = new Uint16Array([0, 1, 2, 2, 1, 3]); return webgl_util.createStaticIndexBuffer(gl, triangleVertexIndices); } exports.createIndexBuffer = createIndexBuffer; function getTextureInternalFormat(gl, numChannels) { if (!environment_1.ENV.get('WEBGL_FLOAT_TEXTURE_ENABLED')) { return gl.RGBA; } if (environment_1.ENV.get('WEBGL_VERSION') === 2) { if (numChannels === 4) { return gl.RGBA32F; } return gl.R32F; } return gl.RGBA; } function getTextureFormat(gl, numChannels) { if (!environment_1.ENV.get('WEBGL_FLOAT_TEXTURE_ENABLED')) { return gl.RGBA; } if (environment_1.ENV.get('WEBGL_VERSION') === 2) { if (numChannels === 4) { return gl.RGBA; } return gl.RED; } return gl.RGBA; } function getTextureType(gl) { if (!environment_1.ENV.get('WEBGL_FLOAT_TEXTURE_ENABLED')) { return gl.UNSIGNED_BYTE; } return gl.FLOAT; } function createAndConfigureTexture(gl, width, height, numChannels) { webgl_util.validateTextureSize(gl, width, height); var texture = webgl_util.createTexture(gl); var tex2d = gl.TEXTURE_2D; var internalFormat = getTextureInternalFormat(gl, numChannels); var format = getTextureFormat(gl, numChannels); webgl_util.callAndCheck(gl, function () { return gl.bindTexture(tex2d, texture); }); webgl_util.callAndCheck(gl, function () { return gl.texParameteri(tex2d, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); }); webgl_util.callAndCheck(gl, function () { return gl.texParameteri(tex2d, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); }); webgl_util.callAndCheck(gl, function () { return gl.texParameteri(tex2d, gl.TEXTURE_MIN_FILTER, gl.NEAREST); }); webgl_util.callAndCheck(gl, function () { return gl.texParameteri(tex2d, gl.TEXTURE_MAG_FILTER, gl.NEAREST); }); webgl_util.callAndCheck(gl, function () { return gl.texImage2D(tex2d, 0, internalFormat, width, height, 0, format, getTextureType(gl), null); }); webgl_util.callAndCheck(gl, function () { return gl.bindTexture(gl.TEXTURE_2D, null); }); return texture; } function createMatrixTexture(gl, rows, columns) { var _a = tex_util.getUnpackedMatrixTextureShapeWidthHeight(rows, columns), width = _a[0], height = _a[1]; var numChannels = 1; return createAndConfigureTexture(gl, width, height, numChannels); } exports.createMatrixTexture = createMatrixTexture; function createColorMatrixTexture(gl, rows, columns) { var _a = tex_util.getColorMatrixTextureShapeWidthHeight(rows, columns), width = _a[0], height = _a[1]; var numChannels = 4; return createAndConfigureTexture(gl, width, height, numChannels); } exports.createColorMatrixTexture = createColorMatrixTexture; function createPackedMatrixTexture(gl, rows, columns) { var _a = tex_util.getPackedMatrixTextureShapeWidthHeight(rows, columns), width = _a[0], height = _a[1]; var numChannels = 4; return createAndConfigureTexture(gl, width, height, numChannels); } exports.createPackedMatrixTexture = createPackedMatrixTexture; function bindVertexProgramAttributeStreams(gl, program, vertexBuffer) { var posOffset = 0; var uvOffset = 3 * 4; var stride = (3 * 4) + (2 * 4); webgl_util.callAndCheck(gl, function () { return gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); }); var success = webgl_util.bindVertexBufferToProgramAttribute(gl, program, 'clipSpacePos', vertexBuffer, 3, stride, posOffset); return success && webgl_util.bindVertexBufferToProgramAttribute(gl, program, 'uv', vertexBuffer, 2, stride, uvOffset); } exports.bindVertexProgramAttributeStreams = bindVertexProgramAttributeStreams; function uploadPixelDataToTexture(gl, texture, pixels) { webgl_util.callAndCheck(gl, function () { return gl.bindTexture(gl.TEXTURE_2D, texture); }); webgl_util.callAndCheck(gl, function () { return gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, pixels); }); webgl_util.callAndCheck(gl, function () { return gl.bindTexture(gl.TEXTURE_2D, null); }); } exports.uploadPixelDataToTexture = uploadPixelDataToTexture; function uploadDataToTexture(gl, texture, width, height, data, numChannels) { var textureFormat = getTextureFormat(gl, numChannels); webgl_util.validateTextureSize(gl, width, height); webgl_util.callAndCheck(gl, function () { return gl.bindTexture(gl.TEXTURE_2D, texture); }); webgl_util.callAndCheck(gl, function () { return gl.texSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, textureFormat, getTextureType(gl), data); }); webgl_util.callAndCheck(gl, function () { return gl.bindTexture(gl.TEXTURE_2D, null); }); } function uploadMatrixToTexture(gl, texture, rows, columns, matrix, numChannels) { var _a = tex_util.getUnpackedMatrixTextureShapeWidthHeight(rows, columns), w = _a[0], h = _a[1]; var unpackedArray; if (environment_1.ENV.get('WEBGL_FLOAT_TEXTURE_ENABLED')) { var channelsPerTexture = numChannels === 1 ? webgl_util.getChannelsPerTexture() : numChannels; if (channelsPerTexture === 1) { unpackedArray = matrix; } else { unpackedArray = new Float32Array(tex_util.getUnpackedArraySizeFromMatrixSize(matrix.length, channelsPerTexture)); tex_util.encodeMatrixToUnpackedArray(matrix, unpackedArray, channelsPerTexture); } } else { unpackedArray = tex_util.encodeFloatArray(matrix); } uploadDataToTexture(gl, texture, w, h, unpackedArray, numChannels); } exports.uploadMatrixToTexture = uploadMatrixToTexture; function uploadMatrixToPackedTexture(gl, texture, rows, columns, matrix) { var _a = tex_util.getPackedMatrixTextureShapeWidthHeight(rows, columns), w = _a[0], h = _a[1]; var packedRGBA = new Float32Array(tex_util.getPackedRGBAArraySizeFromMatrixShape(rows, columns)); tex_util.encodeMatrixToPackedRGBA(matrix, rows, columns, packedRGBA); var numChannels = 4; uploadDataToTexture(gl, texture, w, h, packedRGBA, numChannels); } exports.uploadMatrixToPackedTexture = uploadMatrixToPackedTexture; function getDownloadTargetArrayBuffer(rows, columns, channelsPerTexture) { var isFloatTexture = environment_1.ENV.get('WEBGL_FLOAT_TEXTURE_ENABLED'); var downloadTarget; if (isFloatTexture) { downloadTarget = new Float32Array(tex_util.getUnpackedArraySizeFromMatrixSize(rows * columns, channelsPerTexture)); } else { downloadTarget = new Uint8Array(rows * columns * channelsPerTexture); } return downloadTarget; } function decodeDownloadTargetArrayBuffer(downloadTarget, rows, columns, channelsPerPixel) { var isFloatTexture = environment_1.ENV.get('WEBGL_FLOAT_TEXTURE_ENABLED'); if (isFloatTexture) { var matrix = new Float32Array(rows * columns); tex_util.decodeMatrixFromUnpackedArray(downloadTarget, matrix, channelsPerPixel); return matrix; } else { return tex_util.decodeToFloatArray(downloadTarget); } } function downloadMatrixFromOutputTextureAsync(gl, getBufferSubDataAsyncExtension, rows, columns) { return __awaiter(this, void 0, void 0, function () { var gl2, channelsPerPixel, downloadTarget, bufferSizeBytes, buffer; return __generator(this, function (_a) { switch (_a.label) { case 0: gl2 = gl; channelsPerPixel = 4; downloadTarget = getDownloadTargetArrayBuffer(rows, columns, channelsPerPixel); bufferSizeBytes = downloadTarget instanceof Float32Array ? downloadTarget.length * 4 : downloadTarget; buffer = gl.createBuffer(); webgl_util.callAndCheck(gl, function () { return gl.bindBuffer(gl2.PIXEL_PACK_BUFFER, buffer); }); webgl_util.callAndCheck(gl, function () { return gl.bufferData(gl2.PIXEL_PACK_BUFFER, bufferSizeBytes, gl.STATIC_DRAW); }); webgl_util.callAndCheck(gl, function () { return gl2.readPixels(0, 0, columns, rows, gl.RGBA, getTextureType(gl), 0); }); return [4, getBufferSubDataAsyncExtension.getBufferSubDataAsync(gl2.PIXEL_PACK_BUFFER, 0, downloadTarget)]; case 1: _a.sent(); return [2, decodeDownloadTargetArrayBuffer(downloadTarget, rows, columns, channelsPerPixel)]; } }); }); } exports.downloadMatrixFromOutputTextureAsync = downloadMatrixFromOutputTextureAsync; function downloadMatrixFromOutputTexture(gl, rows, columns) { var _a = tex_util.getUnpackedMatrixTextureShapeWidthHeight(rows, columns), w = _a[0], h = _a[1]; var channelsPerPixel = 4; var downloadTarget = getDownloadTargetArrayBuffer(rows, columns, channelsPerPixel); webgl_util.callAndCheck(gl, function () { return gl.readPixels(0, 0, w, h, gl.RGBA, getTextureType(gl), downloadTarget); }); return decodeDownloadTargetArrayBuffer(downloadTarget, rows, columns, channelsPerPixel); } exports.downloadMatrixFromOutputTexture = downloadMatrixFromOutputTexture; function downloadMatrixFromRGBAColorTexture(gl, rows, columns, channels) { var size = rows * columns * 4; var downloadTarget = new Uint8Array(size); webgl_util.callAndCheck(gl, function () { return gl.readPixels(0, 0, columns, rows, gl.RGBA, gl.UNSIGNED_BYTE, downloadTarget); }); var packedRGBA = new Float32Array(size); for (var i = 0; i < downloadTarget.length; i++) { packedRGBA[i] = downloadTarget[i]; } var matrix = new Float32Array(rows * columns * channels); tex_util.decodeMatrixFromUnpackedColorRGBAArray(packedRGBA, matrix, channels); return matrix; } exports.downloadMatrixFromRGBAColorTexture = downloadMatrixFromRGBAColorTexture; function downloadMatrixFromPackedOutputTexture(gl, rows, columns) { var _a = tex_util.getPackedMatrixTextureShapeWidthHeight(rows, columns), w = _a[0], h = _a[1]; var packedRGBA = new Float32Array(tex_util.getPackedRGBAArraySizeFromMatrixShape(rows, columns)); webgl_util.callAndCheck(gl, function () { return gl.readPixels(0, 0, w, h, gl.RGBA, getTextureType(gl), packedRGBA); }); var matrix = new Float32Array(rows * columns); return tex_util.decodeMatrixFromPackedRGBA(packedRGBA, rows, columns, matrix); } exports.downloadMatrixFromPackedOutputTexture = downloadMatrixFromPackedOutputTexture; //# sourceMappingURL=gpgpu_util.js.map