lottery
🎉🌟✨🎈年会抽奖程序,基于 Express + Three.js的 3D 球体抽奖程序,奖品🧧🎁,文字,图片,抽奖规则均可配置,😜抽奖人员信息Excel一键导入😍,抽奖结果Excel导出😎,给你的抽奖活动带来全新酷炫体验🚀🚀🚀
GPU.js is a JavaScript Acceleration library for GPGPU (General purpose computing on GPUs) in JavaScript for Web and Node. GPU.js automatically transpiles simple JavaScript functions into shader language and compiles them so they run on your GPU. In case a GPU is not available, the functions will still run in regular JavaScript. For some more quick concepts, see Quick Concepts on the wiki.
New to GPU programming? Learn GPGPU in your browser — a free, hands-on course that teaches the subject itself, not just this library. See Learn GPGPU below.
Creates a GPU accelerated kernel transpiled from a javascript function that computes a single element in the 512 x 512 matrix (2D array). The kernel functions are ran in tandem on the GPU often resulting in very fast computations! You can run a benchmark of this here. Typically, it will run 1-15x faster depending on your hardware. Matrix multiplication (perform matrix multiplication on 2 matrices of size 512 x 512) written in GPU.js:
<script src="dist/gpu-browser.min.js"></script>
<script>
// GPU is a constructor and namespace for browser
const gpu = new GPU();
const multiplyMatrix = gpu.createKernel(function(a, b) {
let sum = 0;
for (let i = 0; i < 512; i++) {
sum += a[this.thread.y][i] * b[i][this.thread.x];
}
return sum;
}).setOutput([512, 512]);
const c = multiplyMatrix(a, b);
</script>
https://unpkg.com/gpu.js@latest/dist/gpu-browser.min.js
https://cdn.jsdelivr.net/npm/gpu.js@latest/dist/gpu-browser.min.js
const { GPU } = require('gpu.js');
const gpu = new GPU();
const multiplyMatrix = gpu.createKernel(function(a, b) {
let sum = 0;
for (let i = 0; i < 512; i++) {
sum += a[this.thread.y][i] * b[i][this.thread.x];
}
return sum;
}).setOutput([512, 512]);
const c = multiplyMatrix(a, b);
import { GPU } from 'gpu.js';
const gpu = new GPU();
const multiplyMatrix = gpu.createKernel(function(a: number[][], b: number[][]) {
let sum = 0;
for (let i = 0; i < 512; i++) {
sum += a[this.thread.y][i] * b[i][this.thread.x];
}
return sum;
}).setOutput([512, 512]);
const c = multiplyMatrix(a, b) as number[][];
Click here for more typescript examples.
Warning
The next major version of GPU.js will make every kernel call return a Promise. This is a breaking API change: synchronous kernel calls as you write them today will not survive the v3 upgrade unchanged. Code written against mode: 'async' (new in 2.20.0) already conforms and will run on v3 unchanged — the migration guide below is five steps.
This breaks the API you are using today, so it warrants both notice and an apology. We owe you the apology because the original synchronous design was not forward-thinking, and we should have started async in the first place. A GPU is an asynchronous device: you hand it work, and the results are ready later. WebGL let this library pretend otherwise — readPixels silently freezes the page until the GPU catches up, and we built our API on that pretense because it made the first example look like an ordinary function call. The cost has been paid by every user since: every kernel readback blocks the main thread for its full duration (measurably ~96% of a readback-heavy loop frozen, in one stall as long as the whole loop), and WebGPU — which has no synchronous readback at all, correctly — cannot be offered under the synchronous contract except as a walled-off special mode. An async-first API would have cost one await in the examples and none of this debt.
v3 corrects the mistake: async everywhere, one contract, every backend. The WebGL backends keep a synchronous escape hatch (setAsyncMode(false)) through the migration; WebGPU can never offer one.
Async-by-default is not an aesthetic preference — it is the price of making WebGPU a first-class backend instead of a walled-off special mode, and WebGPU earns that price twice over.
Performance. Measured on the same kernels, same machine (Apple M1 Max), against our own WebGL2 backend at its best:
Accuracy. This one matters more than the speed. Every GPU backend before WebGPU computes by pretending a fragment shader is a compute unit, and this library carries years of scar tissue from that pretense — workarounds you may be relying on without knowing it:
precision: 'unsigned' mode, every float in and out of a kernel is encoded into an 8-bit-per-channel RGBA pixel and decoded on the far side — a quantizing round-trip. WebGPU kernels read and write raw IEEE-754 f32 storage buffers; there is no encode step to lose bits in.fixIntegerDivisionAccuracy setting exists because some GPUs return 2.999… for 9/3 and this library has to patch around them card by card. WGSL has true 32-bit integers with exact division. No setting, no patch, correct by construction.data[i] means element i, at any size.d3dcompiler_47.dll miscompiling a nested texture read, and it was invisible on every other platform. WGSL is a smaller, more rigorously specified language with a conformance-tested compilation path; entire categories of that risk simply do not apply to compute shaders reading storage buffers.The synchronous API is the only thing standing between users and those improvements being the default. That is why it goes.
The v3 contract is available today — opt in with mode: 'async' (or asyncMode: true per kernel) and your code is already v3-shaped:
// v2 (sync)
const gpu = new GPU();
const kernel = gpu.createKernel(fn).setOutput([512, 512]);
const result = kernel(a, b);
// v3 (async) — works today with { mode: 'async' }
const gpu = new GPU({ mode: 'async' });
const kernel = gpu.createKernel(fn).setOutput([512, 512]);
const result = await kernel(a, b);
await every kernel call. The resolved value has exactly the shape the sync call returned — nothing else about your code changes. Callers become async functions; at the top level, wrap in an async IIFE or use top-level await.await: for (…) { total = await step(total); } — iteration order and semantics are unchanged.await result.toArray(). await is harmless on the synchronous backends' textures, so this form is portable across all backends today.pipeline: true and await only the end. Handles pass between kernels without readback, exactly as before; you pay one await at the final readback instead of a main-thread stall at every stage.mode: 'async' in v2 will run unchanged on v3.Notice documentation is off? We do try our hardest, but if you find something, please bring it to our attention, or become a contributor!
GPU Settingsgpu.createKernel Settings
Learn GPGPU in your browser — a free, hands-on course built on GPU.js. Fifteen lessons across three modules, roughly ten hours, with no toolchain to install: you write real kernels in the page and run them on your own GPU, with the results in front of you.
The point worth making is that it teaches GPGPU, not just this library. GPU.js is the vehicle, chosen because JavaScript in a browser is the shortest path from "no setup" to "code running on your GPU" — but what you take away is the subject itself, and it transfers:
this.thread is CUDA's threadIdx/blockIdx, WGSL's global_invocation_id, and OpenCL's get_global_id() wearing different clothes. Once you think in kernels, the syntax is a detail.| module | lessons |
|---|---|
| 1 — Fundamentals | Hello, Kernel · Data In, Data Out · Thinking in Parallel · Pipelines & Textures · Measuring Speed Honestly |
| 2 — Real algorithms | Matrix Multiply · Reductions · Convolution & Filters · Monte Carlo Methods · N-Body Gravity |
| 3 — Graphics | Pixels from Scratch · Escape-Time Fractals · Cellular Automata · Reaction–Diffusion · Ray-Marched Metaballs |
Start at Hello, Kernel — if you can write a JavaScript for loop, you have the prerequisites.
Representative performance factor: 1024×1024 matrix multiplication including readback, versus the CPU backend on the same machine (Apple M1 Max, Chromium; your hardware will vary — run node scripts/benchmark-webgpu.mjs for yours).
| Backend | Environment | Technology | Perf factor | Notes |
|---|---|---|---|---|
webgpu New in 2.20.0! |
Browser | WGSL compute shaders | ~370× | Async API; opt-in via mode: 'webgpu' or automatic via mode: 'async' |
webgl2 |
Browser | GLSL ES 3.00 fragment shaders | ~127× | The default browser backend. 2.20.0 renders scalar single-precision kernels to R32F and reads back one float per value where the driver allows |
webgl |
Browser | GLSL ES 1.00 fragment shaders | ~87× | Fallback for older browsers |
headlessgl |
Node | GLSL ES 1.00 via ANGLE | ~123× | The default Node backend |
cpu |
Anywhere | Plain JavaScript | 1× | Guaranteed fallback; also the reference for correctness |
GPU.js in the wild, all around the net. Add yours here!
More examples with screenshots: gpu.rocks examples gallery
Libraries and tools built on GPU.js:
A note on CodePen: its JavaScript "loop protection" rewrites loops inside kernel functions (injecting window.CP.shouldStopExecution(...)), which breaks kernel transpilation. Disable loop protection in the pen's JS settings, or use Observable/JSFiddle instead.
||||||| 6d7dde3
On Linux, ensure you have the correct header files installed: sudo apt install mesa-common-dev libxi-dev (adjust for your distribution)
npm install gpu.js --save
yarn add gpu.js
const { GPU } = require('gpu.js');
const gpu = new GPU();
import { GPU } from 'gpu.js';
const gpu = new GPU();
Download the latest version of GPU.js and include the files in your HTML page using the following tags:
<script src="dist/gpu-browser.min.js"></script>
<script>
const gpu = new GPU();
</script>
GPU SettingsSettings are an object used to create an instance of GPU. Example: new GPU(settings)
canvas: HTMLCanvasElement. Optional. For sharing canvas. Example: use THREE.js and GPU.js on same canvas.context: WebGL2RenderingContext or WebGLRenderingContext. For sharing rendering context. Example: use THREE.js and GPU.js on same rendering context.mode: Defaults to 'gpu', other values generally for debugging:
WebGLKernel for transpiling a kernelWebGL2Kernel for transpiling a kernelHeadlessGLKernel for transpiling a kernelCPUKernel for transpiling a kernelWebGPUKernel — kernels compile to WGSL compute shaders over storage buffers. Explicit opt-in only, never auto-selected, because every kernel call returns a Promise of its result (WebGPU readback is inherently asynchronous). Check GPU.isWebGPUSupported (synchronous, navigator.gpu presence) or await GPU.isWebGPUAvailable() (requests an actual adapter).asyncMode on for every kernel, and upgrades a kernel to webgpu on its first call if an adapter answers — falling back to the proven backend if the upgraded kernel cannot handle it. Write await kernel(...) once and the same code runs everywhere:const gpu = new GPU({ mode: 'async' });
const kernel = gpu.createKernel(function(a) {
return a[this.thread.x] * 2;
}).setOutput([64]);
const result = await kernel(myArray); // webgpu, webgl2 or cpu underneath
onIstanbulCoverageVariable: Removed in v2.11.0, use v8 coverageremoveIstanbulCoverage: Removed in v2.11.0, use v8 coveragegpu.createKernel SettingsSettings are an object used to create a kernel or kernelMap. Example: gpu.createKernel(settings)
output or kernel.setOutput(output): array or object that describes the output of kernel. When using kernel.setOutput() you can call it after the kernel has compiled if kernel.dynamicOutput is true, to resize your output. Example:
[width], [width, height], or [width, height, depth]{ x: width, y: height, z: depth }pipeline or kernel.setPipeline(true) New in V2!: boolean, default = false
kernel() calls to output a Texture. To get array's from a Texture, use:const result = kernel(); result.toArray();
kernel(texture);
asyncMode or kernel.setAsyncMode(boolean) New!: boolean, default = false - every call to the kernel returns a Promise of the usual result. On webgl2 the readback goes through a pixel-pack buffer and a fence, so the main thread stays free while the GPU works (a synchronous kernel call blocks it for the whole readback); on webgpu kernels are always asynchronous; the other backends resolve their synchronous result so the calling contract is uniform everywhere. Adds a small per-readback latency on webgl2 (fence completion granularity) in exchange for the unblocked main thread — pipeline intermediate kernels and await only final results where that matters. See mode: 'async' for automatic backend selection under this contract.graphical or kernel.setGraphical(boolean): boolean, default = falseloopMaxIterations or kernel.setLoopMaxIterations(number): number, default = 1000constants or kernel.setConstants(object): object, default = nulldynamicOutput or kernel.setDynamicOutput(boolean): boolean, default = false - turns dynamic output on or offdynamicArguments or kernel.setDynamicArguments(boolean): boolean, default = false - turns dynamic arguments (use different size arrays and textures) on or offoptimizeFloatMemory or kernel.setOptimizeFloatMemory(boolean) New in V2!: boolean - causes a float32 texture to use all 4 channels rather than 1, using less memory, but consuming more GPU.precision or kernel.setPrecision('unsigned' | 'single') New in V2!: 'single' or 'unsigned' - if 'single' output texture uses float32 for each colour channel rather than 8fixIntegerDivisionAccuracy or kernel.setFixIntegerDivisionAccuracy(boolean) : boolean - some cards have accuracy issues dividing by factors of three and some other primes (most apple kit?). Default on for affected cards, disable if accuracy not required.functions or kernel.setFunctions(array): array, array of functions to be used inside kernel. If undefined, inherits from GPU instance. Can also be an array of { source: function, argumentTypes: object, returnType: string }.nativeFunctions or kernel.setNativeFunctions(array): object, defined as: { name: string, source: string, settings: object }. This is generally set via using GPU.addNativeFunction()
injectedNative or kernel.setInjectedNative(string) New in V2!: string, defined as: { functionName: functionSource }. This is for injecting native code before translated kernel functions.subKernels or kernel.setSubKernels(array): array, generally inherited from GPU instance.immutable or kernel.setImmutable(boolean): boolean, default = false
strictIntegers or kernel.setStrictIntegers(boolean): boolean, default = false - allows undefined argumentTypes and function return values to use strict integer declarations.useLegacyEncoder or kernel.setUseLegacyEncoder(boolean): boolean, default false - more info here.tactic or kernel.setTactic('speed' | 'balanced' | 'precision') New in V2!: Set the kernel's tactic for compilation. Allows for compilation to better fit how GPU.js is being used (internally uses lowp for 'speed', mediump for 'balanced', and highp for 'precision'). Default is lowest resolution supported for output.Depending on your output type, specify the intended size of your output. You cannot have an accelerated function that does not specify any output size.
| Output size | How to specify output size | How to reference in kernel |
|---|---|---|
| 1D | [length] |
value[this.thread.x] |
| 2D | [width, height] |
value[this.thread.y][this.thread.x] |
| 3D | [width, height, depth] |
value[this.thread.z][this.thread.y][this.thread.x] |
const settings = {
output: [100]
};
or
// You can also use x, y, and z
const settings = {
output: { x: 100 }
};
Create the function you want to run on the GPU. The first input parameter to createKernel is a kernel function which will compute a single number in the output. The thread identifiers, this.thread.x, this.thread.y or this.thread.z will allow you to specify the appropriate behavior of the kernel function at specific positions of the output.
const kernel = gpu.createKernel(function() {
return this.thread.x;
}, settings);
The created function is a regular JavaScript function, and you can use it like one.
kernel(); // Result: Float32Array[0, 1, 2, 3, ... 99]
Note: Instead of creating an object, you can use the chainable shortcut methods as a neater way of specifying settings.
const kernel = gpu.createKernel(function() {
return this.thread.x;
}).setOutput([100]);
kernel();
// Result: Float32Array[0, 1, 2, 3, ... 99]
GPU.js makes variable declaration inside kernel functions easy. Variable types supported are:
Number (Integer or Number), example: let value = 1 or let value = 1.1Boolean, example: let value = trueArray(2), example: let value = [1, 1]Array(3), example: let value = [1, 1, 1]Array(4), example: let value = [1, 1, 1, 1]private Function, example: function myFunction(value) { return value + 1; }Number kernel example:
const kernel = gpu.createKernel(function() {
const i = 1;
const j = 0.89;
return i + j;
}).setOutput([100]);
Boolean kernel example:
const kernel = gpu.createKernel(function() {
const i = true;
if (i) return 1;
return 0;
}).setOutput([100]);
Array(2) kernel examples:
Using declaration
const kernel = gpu.createKernel(function() {
const array2 = [0.08, 2];
return array2;
}).setOutput([100]);
Directly returned
const kernel = gpu.createKernel(function() {
return [0.08, 2];
}).setOutput([100]);
Array(3) kernel example:
Using declaration
const kernel = gpu.createKernel(function() {
const array2 = [0.08, 2, 0.1];
return array2;
}).setOutput([100]);
Directly returned
const kernel = gpu.createKernel(function() {
return [0.08, 2, 0.1];
}).setOutput([100]);
Array(4) kernel example:
Using declaration
const kernel = gpu.createKernel(function() {
const array2 = [0.08, 2, 0.1, 3];
return array2;
}).setOutput([100]);
Directly returned
const kernel = gpu.createKernel(function() {
return [0.08, 2, 0.1, 3];
}).setOutput([100]);
private Function kernel example:
const kernel = gpu.createKernel(function() {
function myPrivateFunction() {
return [0.08, 2, 0.1, 3];
}
return myPrivateFunction(); // <-- type inherited here
}).setOutput([100]);
Debugging can be done in a variety of ways, and there are different levels of debugging.
new GPU({ mode: 'dev' })
GPU.js into development mode. Here you can insert breakpoints, and be somewhat liberal in how your kernel is developed.const gpu = new GPU({ mode: 'dev' });
const kernel = gpu.createKernel(function(arg1, time) {
// put a breakpoint on the next line, and watch it get hit
const v = arg1[this.thread.y][this.thread.x * time];
return v;
}, { output: [100, 100] });
debugger:
const gpu = new GPU({ mode: 'cpu' });
const kernel = gpu.createKernel(function(arg1, time) {
debugger; // <--NOTICE THIS, IMPORTANT!
const v = arg1[this.thread.y][this.thread.x * time];
return v;
}, { output: [100, 100] });
const gpu = new GPU({ mode: 'cpu' });
const kernel = gpu.createKernel(function(arg1, time) {
const x = this.thread.x * time;
return x; // <--NOTICE THIS, IMPORTANT!
const v = arg1[this.thread.y][x];
return v;
}, { output: [100, 100] });
In this example, we return early the value of x, to see exactly what it is. The rest of the logic is ignored, but now you can see the value that is calculated from x, and debug it.
This is an overly simplified problem.const gpu = new GPU({ mode: 'cpu' });
const kernel = gpu.createKernel(function(arg1, time) {
const x = this.thread.x * time;
if (x < 4 || x > 2) {
// RED
this.color(1, 0, 0); // <--NOTICE THIS, IMPORTANT!
return;
}
if (x > 6 && x < 12) {
// GREEN
this.color(0, 1, 0); // <--NOTICE THIS, IMPORTANT!
return;
}
const v = arg1[this.thread.y][x];
return v;
}, { output: [100, 100], graphical: true });
Here we are making the canvas red or green depending on the value of x.Array, Float32Array, Int16Array, Int8Array, Uint16Array, uInt8Arrayconst { input } = require('gpu.js');
const value = input(flattenedArray, [width, height, depth]);
[x, y, z] where x is the fastest-varying (innermost) index — element (x, y, z) lives at flattenedArray[x + width * (y + height * z)]. A kernel access arg[i][j][k] reads z = i, y = j, x = k, so input(flat, [X, Y, Z]) is equivalent to a nested array of shape [Z][Y][X]:input(new Float32Array([1,2, 3,4, 5,6, 7,8]), [2, 2, 2]) // same as: [ [[1,2],[3,4]], [[5,6],[7,8]] ]
const kernel = gpu.createKernel(function(x) {
return x;
}).setOutput([100]);
kernel(42);
// Result: Float32Array[42, 42, 42, 42, ... 42]
Similarly, with array inputs:
const kernel = gpu.createKernel(function(x) {
return x[this.thread.x % 3];
}).setOutput([100]);
kernel([1, 2, 3]);
// Result: Float32Array[1, 2, 3, 1, ... 1 ]
An HTML Image:
const kernel = gpu.createKernel(function(image) {
const pixel = image[this.thread.y][this.thread.x];
this.color(pixel[0], pixel[1], pixel[2], pixel[3]);
})
.setGraphical(true)
.setOutput([100, 100]);
const image = document.createElement('img');
image.src = 'my/image/source.png';
image.onload = () => {
kernel(image);
// Result: colorful image
document.getElementsByTagName('body')[0].appendChild(kernel.canvas);
};
An Array of HTML Images:
const kernel = gpu.createKernel(function(image) {
const pixel = image[this.thread.z][this.thread.y][this.thread.x];
this.color(pixel[0], pixel[1], pixel[2], pixel[3]);
})
.setGraphical(true)
.setOutput([100, 100]);
const image1 = document.createElement('img');
image1.src = 'my/image/source1.png';
image1.onload = onload;
const image2 = document.createElement('img');
image2.src = 'my/image/source2.png';
image2.onload = onload;
const image3 = document.createElement('img');
image3.src = 'my/image/source3.png';
image3.onload = onload;
const totalImages = 3;
let loadedImages = 0;
function onload() {
loadedImages++;
if (loadedImages === totalImages) {
kernel([image1, image2, image3]);
// Result: colorful image composed of many images
document.getElementsByTagName('body')[0].appendChild(kernel.canvas);
}
};
An HTML Video: New in V2!
const kernel = gpu.createKernel(function(videoFrame) {
const pixel = videoFrame[this.thread.y][this.thread.x];
this.color(pixel[0], pixel[1], pixel[2], pixel[3]);
})
.setGraphical(true)
.setOutput([100, 100]);
const video = new document.createElement('video');
video.src = 'my/video/source.webm';
kernel(image); //note, try and use requestAnimationFrame, and the video should be ready or playing
// Result: video frame
Sometimes, you want to produce a canvas image instead of doing numeric computations. To achieve this, set the graphical flag to true and the output dimensions to [width, height]. The thread identifiers will now refer to the x and y coordinate of the pixel you are producing. Inside your kernel function, use this.color(r,g,b) or this.color(r,g,b,a) to specify the color of the pixel.
For performance reasons, the return value of your function will no longer be anything useful. Instead, to display the image, retrieve the canvas DOM node and insert it into your page.
const render = gpu.createKernel(function() {
this.color(0, 0, 0, 1);
})
.setOutput([20, 20])
.setGraphical(true);
render();
const canvas = render.canvas;
document.getElementsByTagName('body')[0].appendChild(canvas);
Note: To animate the rendering, use requestAnimationFrame instead of setTimeout for optimal performance. For more information, see this.
To make it easier to get pixels from a context, use kernel.getPixels(), which returns a flat array similar to what you get from WebGL's readPixels method.
A note on why: webgl's readPixels returns an array ordered differently from javascript's getImageData.
This makes them behave similarly.
While the values may be somewhat different, because of graphical precision available in the kernel, and alpha, this allows us to easily get pixel data in unified way.
Example:
const render = gpu.createKernel(function() {
this.color(0, 0, 0, 1);
})
.setOutput([20, 20])
.setGraphical(true);
render();
const pixels = render.getPixels();
// [r,g,b,a, r,g,b,a...
Currently, if you need alpha do something like enabling premultipliedAlpha with your own gl context:
const canvas = DOM.canvas(500, 500);
const gl = canvas.getContext('webgl2', { premultipliedAlpha: false });
const gpu = new GPU({
canvas,
context: gl
});
const krender = gpu.createKernel(function(x) {
this.color(this.thread.x / 500, this.thread.y / 500, x[0], x[1]);
})
.setOutput([500, 500])
.setGraphical(true);
Sometimes you want to do multiple math operations on the gpu without the round trip penalty of data transfer from cpu to gpu to cpu to gpu, etc. To aid this there is the combineKernels method.
Note: Kernels can have different output sizes.
const add = gpu.createKernel(function(a, b) {
return a[this.thread.x] + b[this.thread.x];
}).setOutput([20]);
const multiply = gpu.createKernel(function(a, b) {
return a[this.thread.x] * b[this.thread.x];
}).setOutput([20]);
const superKernel = gpu.combineKernels(add, multiply, function(a, b, c) {
return multiply(add(a, b), c);
});
superKernel(a, b, c);
This gives you the flexibility of using multiple transformations but without the performance penalty, resulting in a much much MUCH faster operation.
Sometimes you want to do multiple math operations in one kernel, and save the output of each of those operations. An example is Machine Learning where the previous output is required for back propagation. To aid this there is the createKernelMap method.
const megaKernel = gpu.createKernelMap({
addResult: function add(a, b) {
return a + b;
},
multiplyResult: function multiply(a, b) {
return a * b;
},
}, function(a, b, c) {
return multiply(add(a[this.thread.x], b[this.thread.x]), c[this.thread.x]);
}, { output: [10] });
megaKernel(a, b, c);
// Result: { addResult: Float32Array, multiplyResult: Float32Array, result: Float32Array }
const megaKernel = gpu.createKernelMap([
function add(a, b) {
return a + b;
},
function multiply(a, b) {
return a * b;
}
], function(a, b, c) {
return multiply(add(a[this.thread.x], b[this.thread.x]), c[this.thread.x]);
}, { output: [10] });
megaKernel(a, b, c);
// Result: { 0: Float32Array, 1: Float32Array, result: Float32Array }
This gives you the flexibility of using parts of a single transformation without the performance penalty, resulting in much much MUCH faster operation.
GPU instanceuse gpu.addFunction(function() {}, settings) for adding custom functions to all kernels. Needs to be called BEFORE gpu.createKernel. Example:
gpu.addFunction(function mySuperFunction(a, b) {
return a - b;
});
function anotherFunction(value) {
return value + 1;
}
gpu.addFunction(anotherFunction);
const kernel = gpu.createKernel(function(a, b) {
return anotherFunction(mySuperFunction(a[this.thread.x], b[this.thread.x]));
}).setOutput([20]);
Kernel instanceuse kernel.addFunction(function() {}, settings) for adding custom functions to all kernels. Example:
kernel.addFunction(function mySuperFunction(a, b) {
return a - b;
});
function anotherFunction(value) {
return value + 1;
}
kernel.addFunction(anotherFunction);
const kernel = gpu.createKernel(function(a, b) {
return anotherFunction(mySuperFunction(a[this.thread.x], b[this.thread.x]));
}).setOutput([20]);
To manually strongly type a function you may use settings. By setting this value, it makes the build step of the kernel less resource intensive. Settings take an optional hash values:
returnType: optional, defaults to inference from FunctionBuilder, the value you'd like to return from the function.argumentTypes: optional, defaults to inference from FunctionBuilder for each param, a hash of param names with values of the return types.Example on GPU instance:
gpu.addFunction(function mySuperFunction(a, b) {
return [a - b[1], b[0] - a];
}, { argumentTypes: { a: 'Number', b: 'Array(2)'}, returnType: 'Array(2)' });
Example on Kernel instance:
kernel.addFunction(function mySuperFunction(a, b) {
return [a - b[1], b[0] - a];
}, { argumentTypes: { a: 'Number', b: 'Array(2)'}, returnType: 'Array(2)' });
NOTE: GPU.js infers types if they are not defined and is generally able to detect the types you need, however 'Array(2)', 'Array(3)', and 'Array(4)' are exceptions, at least on the kernel level. Also, it is nice to have power over the automatic type inference system.
function mySuperFunction(a, b) {
return a - b;
}
const kernel = gpu.createKernel(function(a, b) {
return mySuperFunction(a[this.thread.x], b[this.thread.x]);
})
.setOutput([20])
.setFunctions([mySuperFunction]);
GPU.js does type inference when types are not defined, so even if you code weak type, you are typing strongly typed. This is needed because c++, which glsl is a subset of, is, of course, strongly typed. Types that can be used with GPU.js are as follows:
NOTE: These refer the the return type of the kernel function, the actual result will always be a collection in the size of the defined output
Types generally used in the Texture class, for #pipelining or for advanced usage.
const matMult = gpu.createKernel(function(a, b) {
var sum = 0;
for (var i = 0; i < this.constants.size; i++) {
sum += a[this.thread.y][i] * b[i][this.thread.x];
}
return sum;
}, {
constants: { size: 512 },
output: [512, 512],
});
const matMult = gpu.createKernel(function(a, b) {
var sum = 0;
for (var i = 0; i < 512; i++) {
sum += a[this.thread.y][i] * b[i][this.thread.x];
}
return sum;
}).setOutput([512, 512]);
Pipeline is a feature where values are sent directly from kernel to kernel via a texture.
This results in extremely fast computing. This is achieved with the kernel setting pipeline: boolean or by calling kernel.setPipeline(true)
In an effort to make the CPU and GPU work similarly, pipeline on CPU and GPU modes causes the kernel result to be reused when immutable: false (which is default).
If you'd like to keep kernel results around, use immutable: true and ensure you cleanup memory:
texture.delete() when appropriate.When using pipeline mode the outputs from kernels can be cloned using texture.clone().
const kernel1 = gpu.createKernel(function(v) {
return v[this.thread.x];
})
.setPipeline(true)
.setOutput([100]);
const kernel2 = gpu.createKernel(function(v) {
return v[this.thread.x];
})
.setOutput([100]);
const result1 = kernel1(array);
// Result: Texture
console.log(result1.toArray());
// Result: Float32Array[0, 1, 2, 3, ... 99]
const result2 = kernel2(result1);
// Result: Float32Array[0, 1, 2, 3, ... 99]
more like this
🎉🌟✨🎈年会抽奖程序,基于 Express + Three.js的 3D 球体抽奖程序,奖品🧧🎁,文字,图片,抽奖规则均可配置,😜抽奖人员信息Excel一键导入😍,抽奖结果Excel导出😎,给你的抽奖活动带来全新酷炫体验🚀🚀🚀
Firefox and Chrome extensions to prevent Google from making links ugly.
search projects, people, and tags