mirror of
https://github.com/gpujs/gpu.js.git
synced 2025-12-08 20:35:56 +00:00
feat: introduce WebGL._replaceOutputTexture and WebGL._replaceSubOutputTextures to cut down on resource usage feat: All supportable Math.methods added fix: Safari not able to render texture arguments feat: CPU gets a pipeline that acts like GPU with/without immutable
238 lines
5.3 KiB
JavaScript
238 lines
5.3 KiB
JavaScript
const { assert, skip, test, module: describe, only } = require('qunit');
|
|
const { GPU } = require('../../src');
|
|
|
|
describe('features: math object');
|
|
|
|
function mathProps(mode) {
|
|
const props = ['E','LN10','LN2','LOG10E','LOG2E','PI','SQRT1_2','SQRT2'];
|
|
const gpu = new GPU({ mode });
|
|
for (let i = 0; i < props.length; i++) {
|
|
const prop = props[i];
|
|
const kernel = gpu.createKernel(`function() {
|
|
return Math.${prop};
|
|
}`, { output: [1] });
|
|
assert.equal(kernel()[0].toFixed(6), Math[prop].toFixed(6));
|
|
}
|
|
gpu.destroy();
|
|
}
|
|
|
|
test('All Math properties auto', () => {
|
|
mathProps();
|
|
});
|
|
|
|
test('All Math properties gpu', () => {
|
|
mathProps('gpu');
|
|
});
|
|
|
|
(GPU.isWebGLSupported ? test : skip)('All Math properties webgl', () => {
|
|
mathProps('webgl');
|
|
});
|
|
|
|
(GPU.isWebGL2Supported ? test : skip)('All Math properties webgl2', () => {
|
|
mathProps('webgl2');
|
|
});
|
|
|
|
(GPU.isHeadlessGLSupported ? test : skip)('All Math properties headlessgl', () => {
|
|
mathProps('headlessgl');
|
|
});
|
|
|
|
test('All Math properties cpu', () => {
|
|
mathProps('cpu');
|
|
});
|
|
|
|
function singleArgumentMathMethods(mode) {
|
|
const methods = [
|
|
'abs',
|
|
'acos',
|
|
'acosh',
|
|
'asin',
|
|
'asinh',
|
|
'atan',
|
|
'atanh',
|
|
'cbrt',
|
|
'ceil',
|
|
// 'clz32', // not supported, bits directly are hard
|
|
'cos',
|
|
'cosh',
|
|
'exp',
|
|
'expm1',
|
|
'floor',
|
|
'fround',
|
|
// 'hypot', // not supported, dynamically sized
|
|
'log',
|
|
'log10',
|
|
'log1p',
|
|
'log2',
|
|
'round',
|
|
'sign',
|
|
'sin',
|
|
'sinh',
|
|
'sqrt',
|
|
'tan',
|
|
'tanh',
|
|
'trunc',
|
|
];
|
|
|
|
const gpu = new GPU({ mode });
|
|
for (let i = 0; i < methods.length; i++) {
|
|
const method = methods[i];
|
|
const kernel = gpu.createKernel(`function(value) {
|
|
return Math.${method}(value);
|
|
}`, { output: [1] });
|
|
for (let j = 0; j < 10; j++) {
|
|
assert.equal(kernel(j / 10)[0].toFixed(3), Math[method](j / 10).toFixed(3), `Math.${method}(${j / 10})`);
|
|
}
|
|
}
|
|
gpu.destroy();
|
|
}
|
|
|
|
test('Single argument Math methods auto', () => {
|
|
singleArgumentMathMethods();
|
|
});
|
|
|
|
test('Single argument Math methods gpu', () => {
|
|
singleArgumentMathMethods('gpu');
|
|
});
|
|
|
|
(GPU.isWebGLSupported ? test : skip)('Single argument Math methods webgl', () => {
|
|
singleArgumentMathMethods('webgl');
|
|
});
|
|
|
|
(GPU.isWebGL2Supported ? test : skip)('Single argument Math methods webgl2', () => {
|
|
singleArgumentMathMethods('webgl2');
|
|
});
|
|
|
|
(GPU.isHeadlessGLSupported ? test : skip)('Single argument Math methods headlessgl', () => {
|
|
singleArgumentMathMethods('headlessgl');
|
|
});
|
|
|
|
test('Single argument Math methods cpu', () => {
|
|
singleArgumentMathMethods('cpu');
|
|
});
|
|
|
|
function twoArgumentMathMethods(mode) {
|
|
const methods = [
|
|
'atan2',
|
|
'imul',
|
|
'max',
|
|
'min',
|
|
'pow',
|
|
];
|
|
|
|
const gpu = new GPU({ mode });
|
|
for (let i = 0; i < methods.length; i++) {
|
|
const method = methods[i];
|
|
const kernel = gpu.createKernel(`function(value1, value2) {
|
|
return Math.${method}(value1, value2);
|
|
}`, { output: [1] });
|
|
for (let j = 0; j < 10; j++) {
|
|
const value1 = j / 10;
|
|
const value2 = value1;
|
|
assert.equal(kernel(value1, value2)[0].toFixed(3), Math[method](value1, value2).toFixed(3), `Math.${method}(${value1}, ${value2})`);
|
|
}
|
|
}
|
|
gpu.destroy();
|
|
}
|
|
|
|
test('Two argument Math methods auto', () => {
|
|
twoArgumentMathMethods();
|
|
});
|
|
|
|
test('Two argument Math methods gpu', () => {
|
|
twoArgumentMathMethods('gpu');
|
|
});
|
|
|
|
(GPU.isWebGLSupported ? test : skip)('Two argument Math methods webgl', () => {
|
|
twoArgumentMathMethods('webgl');
|
|
});
|
|
|
|
(GPU.isWebGL2Supported ? test : skip)('Two argument Math methods webgl2', () => {
|
|
twoArgumentMathMethods('webgl2');
|
|
});
|
|
|
|
(GPU.isHeadlessGLSupported ? test : skip)('Two argument Math methods headlessgl', () => {
|
|
twoArgumentMathMethods('headlessgl');
|
|
});
|
|
|
|
test('Two argument Math methods cpu', () => {
|
|
twoArgumentMathMethods('cpu');
|
|
});
|
|
|
|
function sqrtABTest(mode) {
|
|
const gpu = new GPU({ mode });
|
|
const f = gpu.createKernel(function(a, b) {
|
|
return Math.sqrt(a[this.thread.x] * b[this.thread.x]);
|
|
}, {
|
|
output : [6]
|
|
});
|
|
const a = [3, 4, 5, 6, 7, 8];
|
|
const b = [3, 4, 5, 6, 7, 8];
|
|
|
|
const res = f(a,b);
|
|
const exp = [3, 4, 5, 6, 7, 8];
|
|
|
|
assert.deepEqual(Array.from(res), exp);
|
|
gpu.destroy();
|
|
}
|
|
|
|
test('sqrtAB auto', () => {
|
|
sqrtABTest(null);
|
|
});
|
|
|
|
test('sqrtAB gpu', () => {
|
|
sqrtABTest('gpu');
|
|
});
|
|
|
|
(GPU.isWebGLSupported ? test : skip)('sqrtAB webgl', () => {
|
|
sqrtABTest('webgl');
|
|
});
|
|
|
|
(GPU.isWebGL2Supported ? test : skip)('sqrtAB webgl2', () => {
|
|
sqrtABTest('webgl2');
|
|
});
|
|
|
|
(GPU.isHeadlessGLSupported ? test : skip)('sqrtAB headlessgl', () => {
|
|
sqrtABTest('headlessgl');
|
|
});
|
|
|
|
test('sqrtAB cpu', () => {
|
|
sqrtABTest('cpu');
|
|
});
|
|
|
|
|
|
function mathRandom(mode) {
|
|
const gpu = new GPU({ mode });
|
|
const kernel = gpu.createKernel(function() {
|
|
return Math.random();
|
|
}, { output: [1] });
|
|
|
|
const result = kernel();
|
|
assert.ok(result[0] > 0 && result[0] < 1, `value was expected to be between o and 1, but was ${result[0]}`);
|
|
}
|
|
|
|
test('random auto', () => {
|
|
mathRandom();
|
|
});
|
|
|
|
test('random gpu', () => {
|
|
mathRandom('gpu');
|
|
});
|
|
|
|
(GPU.isWebGLSupported ? test : skip)('random webgl', () => {
|
|
mathRandom('webgl');
|
|
});
|
|
|
|
(GPU.isWebGL2Supported ? test : skip)('random webgl2', () => {
|
|
mathRandom('webgl2');
|
|
});
|
|
|
|
(GPU.isHeadlessGLSupported ? test : skip)('random headlessgl', () => {
|
|
mathRandom('headlessgl');
|
|
});
|
|
|
|
test('random cpu', () => {
|
|
mathRandom('cpu');
|
|
});
|
|
|
|
|