mirror of
https://github.com/gpujs/gpu.js.git
synced 2026-01-18 16:04:10 +00:00
478 lines
11 KiB
JavaScript
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;
|
|
}(); |