gpu.js/dist/backend/kernel-base.js

478 lines
11 KiB
JavaScript

'use strict';
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var utils = require('../core/utils');
module.exports = function () {
/**
* @constructor BaseKernel
*
* @desc Implements the base class for Kernels, and is used as a
* parent class for all Kernel implementations.
*
* This contains the basic methods needed by all Kernel implementations,
* like setDimensions, addSubKernel, etc.
*
* @prop {Array} paramNames - Name of the parameters of the kernel function
* @prop {String} fnString - Kernel function as a String
* @prop {Array} dimensions - Dimensions of the kernel function, this.thread.x, etc.
* @prop {Boolean} debug - Toggle debug mode
* @prop {String} graphical - Toggle graphical mode
* @prop {number} loopMaxIterations - Maximum number of loop iterations
* @prop {Object} constants - Global constants
* @prop {Array} subKernels - Sub kernels bound to this kernel instance
* @prop {Object} subKernelProperties - Sub kernels bound to this kernel instance as key/value pairs
* @prop {Array} subKernelOutputVariableNames - Names of the variables outputted by the subkerls
*
*/
function BaseKernel(fnString, settings) {
_classCallCheck(this, BaseKernel);
this.paramNames = utils.getParamNamesFromString(fnString);
this.fnString = fnString;
this.output = null;
this.debug = false;
this.graphical = false;
this.loopMaxIterations = 0;
this.constants = null;
this.wraparound = null;
this.hardcodeConstants = null;
this.outputToTexture = null;
this.outputImmutable = null;
this.texSize = null;
this._canvas = null;
this._webGl = null;
this.threadDim = null;
this.floatTextures = null;
this.floatOutput = null;
this.floatOutputForce = null;
this.addFunction = null;
this.functions = null;
this.nativeFunctions = null;
this.subKernels = null;
this.subKernelProperties = null;
this.subKernelNames = null;
this.subKernelOutputVariableNames = null;
this.functionBuilder = null;
this.paramTypes = null;
this.events = {};
for (var p in settings) {
if (!settings.hasOwnProperty(p) || !this.hasOwnProperty(p)) continue;
this[p] = settings[p];
}
if (settings.hasOwnProperty('canvas')) {
this._canvas = settings.canvas;
}
if (settings.hasOwnProperty('output')) {
this.setOutput(settings.output); // Flatten output object
}
if (!this._canvas) this._canvas = utils.initCanvas();
}
_createClass(BaseKernel, [{
key: 'build',
value: function build() {
throw new Error('"build" not defined on Base');
}
/**
* @memberOf KernelBase#
* @function
* @name setupParams
*
* @desc Setup the parameter types for the parameters
* supplied to the Kernel function
*
* @param {Array} args - The actual parameters sent to the Kernel
*
*/
}, {
key: 'setupParams',
value: function setupParams(args) {
var paramTypes = this.paramTypes = [];
for (var i = 0; i < args.length; i++) {
var param = args[i];
var paramType = utils.getArgumentType(param);
paramTypes.push(paramType);
}
}
}, {
key: 'setAddFunction',
value: function setAddFunction(cb) {
this.addFunction = cb;
return this;
}
}, {
key: 'setFunctions',
value: function setFunctions(functions) {
this.functions = functions;
return this;
}
/**
* @memberOf BaseKernel#
* @function
* @name setOutput
*
* @desc Set dimensions of the kernel function
*
* @param {Array|Object} output - The output array to set the kernel output size to
*
*/
}, {
key: 'setOutput',
value: function setOutput(output) {
if (output.hasOwnProperty('x')) {
if (output.hasOwnProperty('y')) {
if (output.hasOwnProperty('z')) {
this.output = [output.x, output.y, output.z];
} else {
this.output = [output.x, output.y];
}
} else {
this.output = [output.x];
}
} else {
this.output = output;
}
return this;
}
/**
* @memberOf BaseKernel#
* @function
* @name setDebug
*
* @desc Toggle debug mode
*
* @param {Boolean} flag - true to enable debug
*
*/
}, {
key: 'setDebug',
value: function setDebug(flag) {
this.debug = flag;
return this;
}
/**
* @memberOf BaseKernel#
* @function
* @name setGraphical
*
* @desc Toggle graphical output mode
*
* @param {Boolean} flag - true to enable graphical output
*
*/
}, {
key: 'setGraphical',
value: function setGraphical(flag) {
this.graphical = flag;
return this;
}
/**
* @memberOf BaseKernel#
* @function
* @name setLoopMaxIterations
*
* @desc Set the maximum number of loop iterations
*
* @param {number} max - iterations count
*
*/
}, {
key: 'setLoopMaxIterations',
value: function setLoopMaxIterations(max) {
this.loopMaxIterations = max;
return this;
}
/**
* @memberOf BaseKernel#
* @function
* @name setConstants
* @desc Set Constants
*/
}, {
key: 'setConstants',
value: function setConstants(constants) {
this.constants = constants;
return this;
}
}, {
key: 'setWraparound',
value: function setWraparound(flag) {
console.warn('Wraparound mode is not supported and undocumented.');
this.wraparound = flag;
return this;
}
}, {
key: 'setHardcodeConstants',
value: function setHardcodeConstants(flag) {
this.hardcodeConstants = flag;
return this;
}
}, {
key: 'setOutputToTexture',
value: function setOutputToTexture(flag) {
this.outputToTexture = flag;
return this;
}
}, {
key: 'setOutputImmutable',
value: function setOutputImmutable(flag) {
this.outputImmutable = flag;
return this;
}
/**
* @memberOf BaseKernel#
* @function
* @name setFloatTextures
*
* @desc Toggle texture output mode
*
* @param {Boolean} flag - true to enable floatTextures
*
*/
}, {
key: 'setFloatTextures',
value: function setFloatTextures(flag) {
this.floatTextures = flag;
return this;
}
/**
* @memberOf BaseKernel#
* @function
* @name setFloatOutput
*
* @desc Toggle output mode
*
* @param {Boolean} flag - true to enable float
*
*/
}, {
key: 'setFloatOutput',
value: function setFloatOutput(flag) {
this.floatOutput = flag;
return this;
}
}, {
key: 'setFloatOutputForce',
value: function setFloatOutputForce(flag) {
this.floatOutputForce = flag;
return this;
}
/**
* @memberOf BaseKernel#
* @function
* @name setCanvas
*
* @desc Bind the canvas to kernel
*
* @param {Canvas} canvas - Canvas to bind
*
*/
}, {
key: 'setCanvas',
value: function setCanvas(canvas) {
this._canvas = canvas;
return this;
}
/**
* @memberOf BaseKernel#
* @function
* @name setCanvas
*
* @desc Bind the webGL instance to kernel
*
* @param {Canvas} webGL - webGL instance to bind
*
*/
}, {
key: 'setWebGl',
value: function setWebGl(webGl) {
this._webGl = webGl;
return this;
}
/**
* @memberOf BaseKernel#
* @function
* @name getCanvas()
*
* @desc Returns the current canvas instance bound to the kernel
*
*/
}, {
key: 'getCanvas',
value: function getCanvas() {
return this._canvas;
}
/**
* @memberOf BaseKernel#
* @function
* @name getWebGl()
*
* @desc Returns the current webGl instance bound to the kernel
*
*/
}, {
key: 'getWebGl',
value: function getWebGl() {
return this._webGl;
}
}, {
key: 'validateOptions',
value: function validateOptions() {
throw new Error('validateOptions not defined');
}
}, {
key: 'exec',
value: function exec() {
return this.execute.apply(this, arguments);
}
}, {
key: 'execute',
value: function execute() {
var _this = this;
//
// Prepare the required objects
//
var args = arguments.length === 1 ? [arguments[0]] : Array.apply(null, arguments);
//
// Setup and return the promise, and execute the function, in synchronous mode
//
return utils.newPromise(function (accept, reject) {
try {
accept(_this.run.apply(_this, args));
} catch (e) {
//
// Error : throw rejection
//
reject(e);
}
});
}
/**
* @memberOf BaseKernel#
* @function
* @name addSubKernel
*
* @desc Add a sub kernel to the root kernel instance.
* This is what `createKernelMap` uses.
*
* @param {String} fnString - function (as a String) of the subKernel to add
*
*/
}, {
key: 'addSubKernel',
value: function addSubKernel(fnString) {
if (this.subKernels === null) {
this.subKernels = [];
this.subKernelNames = [];
}
this.subKernels.push(fnString);
this.subKernelNames.push(utils.getFunctionNameFromString(fnString));
return this;
}
/**
* @memberOf BaseKernel#
* @function
* @name addSubKernelProperty
*
* @desc Add a sub kernel to the root kernel instance, indexed by a property name
* This is what `createKernelMap` uses.
*
* @param {String} property - property key for the subKernel
* @param {String} fnString - function (as a String) of the subKernel to add
*
*/
}, {
key: 'addSubKernelProperty',
value: function addSubKernelProperty(property, fnString) {
if (this.subKernelProperties === null) {
this.subKernelProperties = {};
this.subKernelNames = [];
}
if (this.subKernelProperties.hasOwnProperty(property)) {
throw new Error('cannot add sub kernel ' + property + ', already defined');
}
this.subKernelProperties[property] = fnString;
this.subKernelNames.push(utils.getFunctionNameFromString(fnString));
return this;
}
}, {
key: 'addNativeFunction',
value: function addNativeFunction(name, source) {
this.functionBuilder.addNativeFunction(name, source);
}
}, {
key: 'addNativeVariable',
value: function addNativeVariable(name, variable) {
this.functionBuilder.addNativeVariable(name, variable);
}
}, {
key: 'on',
value: function on(eventName, fn) {
if (!this.events.hasOwnProperty(eventName)) {
this.events[eventName] = [];
}
this.events[eventName].push(fn);
}
}, {
key: 'off',
value: function off(eventName, fn) {
if (!this.events.hasOwnProperty(eventName)) return;
if (!fn) {
delete this.events[eventName];
} else {
var events = this.events[eventName];
var index = events.indexOf(fn);
if (index > -1) {
events.splice(index, 1);
}
}
}
}, {
key: 'trigger',
value: function trigger(eventName) {
if (!this.events.hasOwnProperty(eventName)) return;
var events = this.events[eventName];
for (var i = 0; i < events.length; i++) {
events[i]();
}
}
}]);
return BaseKernel;
}();