@tensorflow/tfjs-core
Version:
Hardware-accelerated JavaScript library for machine intelligence
344 lines • 12.8 kB
JavaScript
"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
Object.defineProperty(exports, "__esModule", { value: true });
var device_util = require("./device_util");
var doc_1 = require("./doc");
var engine_1 = require("./engine");
var util = require("./util");
var Type;
(function (Type) {
Type[Type["NUMBER"] = 0] = "NUMBER";
Type[Type["BOOLEAN"] = 1] = "BOOLEAN";
Type[Type["STRING"] = 2] = "STRING";
})(Type = exports.Type || (exports.Type = {}));
exports.URL_PROPERTIES = [
{ name: 'DEBUG', type: Type.BOOLEAN }, { name: 'IS_BROWSER', type: Type.BOOLEAN },
{ name: 'WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_VERSION', type: Type.NUMBER },
{ name: 'WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_RELIABLE', type: Type.BOOLEAN },
{ name: 'WEBGL_VERSION', type: Type.NUMBER },
{ name: 'WEBGL_FLOAT_TEXTURE_ENABLED', type: Type.BOOLEAN }, {
name: 'WEBGL_GET_BUFFER_SUB_DATA_ASYNC_EXTENSION_ENABLED',
type: Type.BOOLEAN
},
{ name: 'BACKEND', type: Type.STRING }
];
function hasExtension(gl, extensionName) {
var ext = gl.getExtension(extensionName);
return ext != null;
}
function getWebGLRenderingContext(webGLVersion) {
if (webGLVersion === 0) {
throw new Error('Cannot get WebGL rendering context, WebGL is disabled.');
}
var tempCanvas = document.createElement('canvas');
if (webGLVersion === 1) {
return (tempCanvas.getContext('webgl') ||
tempCanvas.getContext('experimental-webgl'));
}
return tempCanvas.getContext('webgl2');
}
function loseContext(gl) {
if (gl != null) {
var loseContextExtension = gl.getExtension('WEBGL_lose_context');
if (loseContextExtension == null) {
throw new Error('Extension WEBGL_lose_context not supported on this browser.');
}
loseContextExtension.loseContext();
}
}
function isWebGLVersionEnabled(webGLVersion) {
var gl = getWebGLRenderingContext(webGLVersion);
if (gl != null) {
loseContext(gl);
return true;
}
return false;
}
function getWebGLDisjointQueryTimerVersion(webGLVersion) {
if (webGLVersion === 0) {
return 0;
}
var queryTimerVersion;
var gl = getWebGLRenderingContext(webGLVersion);
if (hasExtension(gl, 'EXT_disjoint_timer_query_webgl2') &&
webGLVersion === 2) {
queryTimerVersion = 2;
}
else if (hasExtension(gl, 'EXT_disjoint_timer_query')) {
queryTimerVersion = 1;
}
else {
queryTimerVersion = 0;
}
if (gl != null) {
loseContext(gl);
}
return queryTimerVersion;
}
function isFloatTextureReadPixelsEnabled(webGLVersion) {
if (webGLVersion === 0) {
return false;
}
var gl = getWebGLRenderingContext(webGLVersion);
if (webGLVersion === 1) {
if (!hasExtension(gl, 'OES_texture_float')) {
return false;
}
}
else {
if (!hasExtension(gl, 'EXT_color_buffer_float')) {
return false;
}
}
var frameBuffer = gl.createFramebuffer();
var texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
var internalFormat = webGLVersion === 2 ? gl.RGBA32F : gl.RGBA;
gl.texImage2D(gl.TEXTURE_2D, 0, internalFormat, 1, 1, 0, gl.RGBA, gl.FLOAT, null);
gl.bindFramebuffer(gl.FRAMEBUFFER, frameBuffer);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
var frameBufferComplete = (gl.checkFramebufferStatus(gl.FRAMEBUFFER) === gl.FRAMEBUFFER_COMPLETE);
gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.FLOAT, new Float32Array(4));
var readPixelsNoError = gl.getError() === gl.NO_ERROR;
loseContext(gl);
return frameBufferComplete && readPixelsNoError;
}
function isWebGLGetBufferSubDataAsyncExtensionEnabled(webGLVersion) {
if (webGLVersion > 0) {
return false;
}
if (webGLVersion !== 2) {
return false;
}
var gl = getWebGLRenderingContext(webGLVersion);
var isEnabled = hasExtension(gl, 'WEBGL_get_buffer_sub_data_async');
loseContext(gl);
return isEnabled;
}
var Environment = (function () {
function Environment(features) {
this.features = {};
this.registry = {};
if (features != null) {
this.features = features;
}
if (this.get('DEBUG')) {
console.warn('Debugging mode is ON. The output of every math call will ' +
'be downloaded to CPU and checked for NaNs. ' +
'This significantly impacts performance.');
}
}
Environment.setBackend = function (backendType, safeMode) {
if (safeMode === void 0) { safeMode = false; }
if (!(backendType in exports.ENV.registry)) {
throw new Error("Backend type '" + backendType + "' not found in registry");
}
exports.ENV.initBackend(backendType, safeMode);
};
Environment.getBackend = function () {
exports.ENV.initDefaultBackend();
return exports.ENV.currentBackend;
};
Environment.disposeVariables = function () {
exports.ENV.engine.disposeVariables();
};
Environment.memory = function () {
return exports.ENV.engine.memory();
};
Environment.prototype.get = function (feature) {
if (feature in this.features) {
return this.features[feature];
}
this.features[feature] = this.evaluateFeature(feature);
return this.features[feature];
};
Environment.prototype.set = function (feature, value) {
this.features[feature] = value;
};
Environment.prototype.getBestBackendType = function () {
var _this = this;
if (Object.keys(this.registry).length === 0) {
throw new Error('No backend found in registry.');
}
var sortedBackends = Object.keys(this.registry)
.map(function (name) {
return { name: name, entry: _this.registry[name] };
})
.sort(function (a, b) {
return b.entry.priority - a.entry.priority;
});
return sortedBackends[0].name;
};
Environment.prototype.evaluateFeature = function (feature) {
if (feature === 'DEBUG') {
return false;
}
else if (feature === 'IS_BROWSER') {
return typeof window !== 'undefined';
}
else if (feature === 'BACKEND') {
return this.getBestBackendType();
}
else if (feature === 'WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_VERSION') {
var webGLVersion = this.get('WEBGL_VERSION');
if (webGLVersion === 0) {
return 0;
}
return getWebGLDisjointQueryTimerVersion(webGLVersion);
}
else if (feature === 'WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_RELIABLE') {
return this.get('WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_VERSION') > 0 &&
!device_util.isMobile();
}
else if (feature === 'WEBGL_VERSION') {
if (isWebGLVersionEnabled(2)) {
return 2;
}
else if (isWebGLVersionEnabled(1)) {
return 1;
}
return 0;
}
else if (feature === 'WEBGL_FLOAT_TEXTURE_ENABLED') {
return isFloatTextureReadPixelsEnabled(this.get('WEBGL_VERSION'));
}
else if (feature === 'WEBGL_GET_BUFFER_SUB_DATA_ASYNC_EXTENSION_ENABLED') {
return isWebGLGetBufferSubDataAsyncExtensionEnabled(this.get('WEBGL_VERSION'));
}
throw new Error("Unknown feature " + feature + ".");
};
Environment.prototype.setFeatures = function (features) {
this.features = features;
};
Environment.prototype.reset = function () {
this.features = getFeaturesFromURL();
if (this.globalEngine != null) {
this.globalEngine.dispose();
this.globalEngine = null;
}
};
Environment.prototype.initBackend = function (backendType, safeMode) {
if (safeMode === void 0) { safeMode = false; }
this.currentBackend = backendType;
if (this.globalEngine != null) {
this.globalEngine.dispose();
}
var backend = exports.ENV.findBackend(backendType);
this.globalEngine = new engine_1.Engine(backend, safeMode);
};
Environment.prototype.findBackend = function (name) {
if (!(name in this.registry)) {
return null;
}
return this.registry[name].backend;
};
Environment.prototype.registerBackend = function (name, factory, priority) {
if (priority === void 0) { priority = 1; }
if (name in this.registry) {
console.warn(name + " backend was already registered");
}
try {
var backend = factory();
this.registry[name] = { backend: backend, priority: priority };
return true;
}
catch (err) {
console.warn(err.message);
return false;
}
};
Environment.prototype.removeBackend = function (name) {
if (!(name in this.registry)) {
throw new Error(name + " backend not found in registry");
}
this.registry[name].backend.dispose();
delete this.registry[name];
};
Object.defineProperty(Environment.prototype, "engine", {
get: function () {
this.initDefaultBackend();
return this.globalEngine;
},
enumerable: true,
configurable: true
});
Environment.prototype.initDefaultBackend = function () {
if (this.globalEngine == null) {
this.initBackend(exports.ENV.get('BACKEND'), false);
}
};
__decorate([
doc_1.doc({ heading: 'Environment' })
], Environment, "setBackend", null);
__decorate([
doc_1.doc({ heading: 'Environment' })
], Environment, "getBackend", null);
__decorate([
doc_1.doc({ heading: 'Environment' })
], Environment, "disposeVariables", null);
__decorate([
doc_1.doc({ heading: 'Performance', subheading: 'Memory' })
], Environment, "memory", null);
return Environment;
}());
exports.Environment = Environment;
var TENSORFLOWJS_FLAGS_PREFIX = 'tfjsflags';
function getFeaturesFromURL() {
var features = {};
if (typeof window === 'undefined' || typeof window.location === 'undefined') {
return features;
}
var urlParams = util.getQueryParams(window.location.search);
if (TENSORFLOWJS_FLAGS_PREFIX in urlParams) {
var urlFlags_1 = {};
var keyValues = urlParams[TENSORFLOWJS_FLAGS_PREFIX].split(',');
keyValues.forEach(function (keyValue) {
var _a = keyValue.split(':'), key = _a[0], value = _a[1];
urlFlags_1[key] = value;
});
exports.URL_PROPERTIES.forEach(function (urlProperty) {
if (urlProperty.name in urlFlags_1) {
console.log("Setting feature override from URL " + urlProperty.name + ": " +
("" + urlFlags_1[urlProperty.name]));
if (urlProperty.type === Type.NUMBER) {
features[urlProperty.name] = +urlFlags_1[urlProperty.name];
}
else if (urlProperty.type === Type.BOOLEAN) {
features[urlProperty.name] = urlFlags_1[urlProperty.name] === 'true';
}
else if (urlProperty.type === Type.STRING) {
features[urlProperty.name] = urlFlags_1[urlProperty.name];
}
else {
console.warn("Unknown URL param: " + urlProperty.name + ".");
}
}
});
}
return features;
}
function getGlobalNamespace() {
var ns;
if (typeof (window) !== 'undefined') {
ns = window;
}
else if (typeof (global) !== 'undefined') {
ns = global;
}
else {
throw new Error('Could not find a global object');
}
return ns;
}
function getOrMakeEnvironment() {
var ns = getGlobalNamespace();
ns.ENV = ns.ENV || new Environment(getFeaturesFromURL());
return ns.ENV;
}
exports.ENV = getOrMakeEnvironment();
//# sourceMappingURL=environment.js.map