Skip to content

Commit f88d92c

Browse files
feat: Bring back kernel.immutable and kernel.setImmutable() with defaults to false
Along with tests and documentation on which versions are affected. Sorry for the inconvenience! feat: Add more advanced-typescript.ts fix: Alter documentation mentioning v2 fix: Example of fluid.html, to use `immutable`
1 parent 586ab02 commit f88d92c

16 files changed

+280
-177
lines changed

README.md

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,12 @@ const multiplyMatrix = gpu.createKernel(function(a: number[][], b: number[][]) {
7070
const c = multiplyMatrix(a, b) as number[][];
7171
```
7272

73+
[Click here](/examples) for more typescript examples.
74+
7375
# Table of Contents
7476

75-
NOTE: documentation is slightly out of date for the upcoming release of v2. We will fix it! In the mean time, if you'd like to assist (PLEASE) let us know.
77+
Notice documentation is off? We do try our hardest, but if you find something,
78+
[please bring it to our attention](https://github.com/gpujs/gpu.js/issues), or _[become a contributor](#contributors)_!
7679

7780
* [Demos](#demos)
7881
* [Installation](#installation)
@@ -91,7 +94,7 @@ NOTE: documentation is slightly out of date for the upcoming release of v2. We
9194
* [Loops](#loops)
9295
* [Pipelining](#pipelining)
9396
* [Cloning Textures](#cloning-textures-new-in-v2)
94-
* [Cleanup pipeline texture memory](#cleanup-pipeline-texture-memory-new-in-v2)
97+
* [Cleanup pipeline texture memory](#cleanup-pipeline-texture-memory-new-in-v24)
9598
* [Offscreen Canvas](#offscreen-canvas)
9699
* [Cleanup](#cleanup)
97100
* [Flattened typed array support](#flattened-typed-array-support)
@@ -235,7 +238,8 @@ Settings are an object used to create a `kernel` or `kernelMap`. Example: `gpu.
235238
* VERY IMPORTANT! - Use this to add special native functions to your environment when you need specific functionality is needed.
236239
* `injectedNative` or `kernel.setInjectedNative(string)` **New in V2!**: string, defined as: `{ functionName: functionSource }`. This is for injecting native code before translated kernel functions.
237240
* `subKernels` or `kernel.setSubKernels(array)`: array, generally inherited from `GPU` instance.
238-
* ~~`immutable` or `kernel.setImmutable(boolean)`: boolean, default = `false`~~ Deprecated
241+
* `immutable` or `kernel.setImmutable(boolean)`: boolean, default = `false`
242+
* VERY IMPORTANT! - This was removed in v2.4.0 - v2.7.0, and brought back in v2.8.0 [by popular demand](https://github.com/gpujs/gpu.js/issues/572), please upgrade to get the feature
239243
* `strictIntegers` or `kernel.setStrictIntegers(boolean)`: boolean, default = `false` - allows undefined argumentTypes and function return values to use strict integer declarations.
240244
* `useLegacyEncoder` or `kernel.setUseLegacyEncoder(boolean)`: boolean, default `false` - more info [here](https://github.com/gpujs/gpu.js/wiki/Encoder-details).
241245
* `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.
@@ -845,13 +849,15 @@ const result2 = kernel2(result1);
845849
```
846850

847851
### Cleanup pipeline texture memory **New in V2.4!**
848-
Handling minimal amounts of GPU memory is handled internally, but a good practice is to clean up memory you no longer need.
852+
When using `kernel.immutable = true` recycling GPU memory is handled internally, but a good practice is to clean up memory you no longer need it.
849853
Cleanup kernel outputs by using `texture.delete()` to keep GPU memory as small as possible.
850854

851855
NOTE: Internally textures will only release from memory if there are no references to them.
852-
When using pipeline mode on a kernel K the output for each call will be a newly allocated texture T.
853-
If, after getting texture T as an output, T.delete() is called, the next call to K will reuse T as its output texture.
856+
When using pipeline mode on a kernel `K` the output for each call will be a newly allocated texture `T`.
857+
If, after getting texture `T` as an output, `T.delete()` is called, the next call to K will reuse `T` as its output texture.
854858

859+
Alternatively, if you'd like to clear out a `texture` and yet keep it in memory, you may use `texture.clear()`, which
860+
will cause the `texture` to persist in memory, but its internal values to become all zeros.
855861

856862
## Offscreen Canvas
857863
GPU.js supports offscreen canvas where available. Here is an example of how to use it with two files, `gpu-worker.js`, and `index.js`:
@@ -1114,6 +1120,8 @@ const result = kernelMap();
11141120
console.log(result as number[][][]);
11151121
```
11161122

1123+
[Click here](/examples) for more typescript examples.
1124+
11171125
## Destructured Assignments **New in V2!**
11181126
Destructured Objects and Arrays work in GPU.js.
11191127
* Object destructuring

dist/gpu-browser-core.js

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
*
55
* GPU Accelerated JavaScript
66
*
7-
* @version 2.7.0
8-
* @date Tue Mar 10 2020 15:46:55 GMT-0400 (Eastern Daylight Time)
7+
* @version 2.8.0
8+
* @date Wed Mar 11 2020 07:33:36 GMT-0400 (Eastern Daylight Time)
99
*
1010
* @license MIT
1111
* The MIT License
@@ -5095,7 +5095,7 @@ class GLKernel extends Kernel {
50955095
}
50965096

50975097
renderTexture() {
5098-
return this.texture.clone();
5098+
return this.immutable ? this.texture.clone() : this.texture;
50995099
}
51005100
readPackedPixelsToUint8Array() {
51015101
if (this.precision !== 'unsigned') throw new Error('Requires this.precision to be "unsigned"');
@@ -5150,8 +5150,14 @@ class GLKernel extends Kernel {
51505150
const result = {
51515151
result: this.renderOutput(),
51525152
};
5153-
for (let i = 0; i < this.subKernels.length; i++) {
5154-
result[this.subKernels[i].property] = this.mappedTextures[i].clone();
5153+
if (this.immutable) {
5154+
for (let i = 0; i < this.subKernels.length; i++) {
5155+
result[this.subKernels[i].property] = this.mappedTextures[i].clone();
5156+
}
5157+
} else {
5158+
for (let i = 0; i < this.subKernels.length; i++) {
5159+
result[this.subKernels[i].property] = this.mappedTextures[i];
5160+
}
51555161
}
51565162
return result;
51575163
}
@@ -5259,6 +5265,7 @@ class GLKernel extends Kernel {
52595265
}
52605266

52615267
updateTextureArgumentRefs(kernelValue, arg) {
5268+
if (!this.immutable) return;
52625269
if (this.texture.texture === arg.texture) {
52635270
const { prevArg } = kernelValue;
52645271
if (prevArg) {
@@ -6317,7 +6324,7 @@ class Kernel {
63176324
}
63186325

63196326
setImmutable(flag) {
6320-
utils.warnDeprecated('method', 'setImmutable');
6327+
this.immutable = flag;
63216328
return this;
63226329
}
63236330

@@ -10260,7 +10267,7 @@ class WebGLKernel extends GLKernel {
1026010267
gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer);
1026110268
this._setupOutputTexture();
1026210269
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
10263-
return this.texture.clone();
10270+
return this.immutable ? this.texture.clone() : this.texture;
1026410271
}
1026510272
gl.bindRenderbuffer(gl.RENDERBUFFER, null);
1026610273
gl.bindFramebuffer(gl.FRAMEBUFFER, null);

dist/gpu-browser-core.min.js

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/gpu-browser.js

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
*
55
* GPU Accelerated JavaScript
66
*
7-
* @version 2.7.0
8-
* @date Tue Mar 10 2020 15:46:55 GMT-0400 (Eastern Daylight Time)
7+
* @version 2.8.0
8+
* @date Wed Mar 11 2020 07:33:35 GMT-0400 (Eastern Daylight Time)
99
*
1010
* @license MIT
1111
* The MIT License
@@ -9548,7 +9548,7 @@ class GLKernel extends Kernel {
95489548
}
95499549

95509550
renderTexture() {
9551-
return this.texture.clone();
9551+
return this.immutable ? this.texture.clone() : this.texture;
95529552
}
95539553
readPackedPixelsToUint8Array() {
95549554
if (this.precision !== 'unsigned') throw new Error('Requires this.precision to be "unsigned"');
@@ -9603,8 +9603,14 @@ class GLKernel extends Kernel {
96039603
const result = {
96049604
result: this.renderOutput(),
96059605
};
9606-
for (let i = 0; i < this.subKernels.length; i++) {
9607-
result[this.subKernels[i].property] = this.mappedTextures[i].clone();
9606+
if (this.immutable) {
9607+
for (let i = 0; i < this.subKernels.length; i++) {
9608+
result[this.subKernels[i].property] = this.mappedTextures[i].clone();
9609+
}
9610+
} else {
9611+
for (let i = 0; i < this.subKernels.length; i++) {
9612+
result[this.subKernels[i].property] = this.mappedTextures[i];
9613+
}
96089614
}
96099615
return result;
96109616
}
@@ -9712,6 +9718,7 @@ class GLKernel extends Kernel {
97129718
}
97139719

97149720
updateTextureArgumentRefs(kernelValue, arg) {
9721+
if (!this.immutable) return;
97159722
if (this.texture.texture === arg.texture) {
97169723
const { prevArg } = kernelValue;
97179724
if (prevArg) {
@@ -10770,7 +10777,7 @@ class Kernel {
1077010777
}
1077110778

1077210779
setImmutable(flag) {
10773-
utils.warnDeprecated('method', 'setImmutable');
10780+
this.immutable = flag;
1077410781
return this;
1077510782
}
1077610783

@@ -14713,7 +14720,7 @@ class WebGLKernel extends GLKernel {
1471314720
gl.bindFramebuffer(gl.FRAMEBUFFER, this.framebuffer);
1471414721
this._setupOutputTexture();
1471514722
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
14716-
return this.texture.clone();
14723+
return this.immutable ? this.texture.clone() : this.texture;
1471714724
}
1471814725
gl.bindRenderbuffer(gl.RENDERBUFFER, null);
1471914726
gl.bindFramebuffer(gl.FRAMEBUFFER, null);

dist/gpu-browser.min.js

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

examples/advanced-typescript.ts

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/**
2+
* This is an arbitrary example (overly complex with types for overly simplified kernel) to show type inheritance
3+
* throughout the kernel's usage.
4+
*
5+
* The whole idea here is that you can define custom:
6+
* - `constants`
7+
* - `this` context
8+
* - mapped kernels
9+
* - arguments
10+
* - kernel output
11+
*/
12+
13+
import { GPU, Texture, IKernelFunctionThis, IConstantsThis } from '../src';
14+
15+
const gpu = new GPU();
16+
17+
interface IConstants extends IConstantsThis {
18+
rotation: number,
19+
}
20+
21+
interface IThis extends IKernelFunctionThis {
22+
constants: IConstants,
23+
}
24+
25+
function kernelFunction(this: IThis, degrees: number, divisors: [number, number]): [number, number] {
26+
const bounds = subKernel(this.constants.rotation * degrees);
27+
return [bounds[0] / divisors[0], bounds[1] / divisors[1]];
28+
}
29+
30+
function subKernel(value: number): [number, number] {
31+
return [-value, value];
32+
}
33+
34+
const kernelMap = gpu.createKernelMap<typeof kernelFunction>({
35+
test: subKernel,
36+
}, kernelFunction)
37+
.setConstants<IConstants>({
38+
rotation: 45,
39+
})
40+
.setOutput([1])
41+
.setPrecision('single')
42+
.setPipeline(true)
43+
.setImmutable(true);
44+
45+
const { test, result } = kernelMap(360, [256, 512]);
46+
const testTexture = test as Texture;
47+
const resultTexture = result as Texture;
48+
49+
console.log(testTexture.toArray() as [number, number][]);
50+
console.log(resultTexture.toArray() as [number, number][]);
51+
52+
testTexture.delete();
53+
resultTexture.delete();
54+
55+
kernelMap.destroy();

examples/fluid.html

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@
294294
output: [ this.particleCount*3 ],
295295
pipeline: true,
296296
tactic: 'speed',
297+
immutable: true,
297298
});
298299

299300
/*
@@ -312,6 +313,7 @@
312313
constants: { particleCount: this.particleCount, pitch: 3 },
313314
loopMaxIterations: this.particleCount,
314315
tactic: 'speed',
316+
immutable: true,
315317
});
316318

317319
this.setVelocity = gpu.createKernel(function(list, index, camDir, amount) {
@@ -326,6 +328,7 @@
326328
constants: { particleCount: this.particleCount, pitch: 3 },
327329
loopMaxIterations: this.particleCount,
328330
tactic: 'speed',
331+
immutable: true,
329332
});
330333

331334
/*
@@ -339,6 +342,7 @@
339342
pipeline: true,
340343
loopMaxIterations: this.particleCount,
341344
tactic: 'speed',
345+
immutable: true,
342346
});
343347

344348
this.rotateCamera = gpu.createKernel(function(rotLR, rotUD, camCenter, camDir, camUp, camNearWidth, camFarWidth, camDist) {
@@ -360,7 +364,8 @@
360364
}, {
361365
output: [ 3 ],
362366
tactic: 'speed',
363-
pipeline: true
367+
pipeline: true,
368+
immutable: true,
364369
});
365370

366371
this.updateCameraPosition = gpu.createKernel(function(camDir, camP, moveTFR, dt) {
@@ -373,7 +378,8 @@
373378
}, {
374379
output: [3],
375380
tactic: 'speed',
376-
pipeline: true
381+
pipeline: true,
382+
immutable: true,
377383
});
378384

379385
/*
@@ -784,6 +790,7 @@
784790
output: [3],
785791
pipeline: true,
786792
tactic: 'speed',
793+
immutable: true,
787794
});
788795

789796
this.crossv = gpu.createKernel(function(a, b) {
@@ -800,6 +807,7 @@
800807
output: [3],
801808
pipeline: true,
802809
tactic: 'speed',
810+
immutable: true,
803811
});
804812
}
805813

package-lock.json

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "gpu.js",
3-
"version": "2.7.0",
3+
"version": "2.8.0",
44
"description": "GPU Accelerated JavaScript",
55
"engines": {
66
"node": ">=8.0.0"

src/backend/gl/kernel.js

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -789,7 +789,7 @@ class GLKernel extends Kernel {
789789
}
790790

791791
renderTexture() {
792-
return this.texture.clone();
792+
return this.immutable ? this.texture.clone() : this.texture;
793793
}
794794
readPackedPixelsToUint8Array() {
795795
if (this.precision !== 'unsigned') throw new Error('Requires this.precision to be "unsigned"');
@@ -850,8 +850,14 @@ class GLKernel extends Kernel {
850850
const result = {
851851
result: this.renderOutput(),
852852
};
853-
for (let i = 0; i < this.subKernels.length; i++) {
854-
result[this.subKernels[i].property] = this.mappedTextures[i].clone();
853+
if (this.immutable) {
854+
for (let i = 0; i < this.subKernels.length; i++) {
855+
result[this.subKernels[i].property] = this.mappedTextures[i].clone();
856+
}
857+
} else {
858+
for (let i = 0; i < this.subKernels.length; i++) {
859+
result[this.subKernels[i].property] = this.mappedTextures[i];
860+
}
855861
}
856862
return result;
857863
}
@@ -964,6 +970,7 @@ class GLKernel extends Kernel {
964970
* @param {GLTexture} arg
965971
*/
966972
updateTextureArgumentRefs(kernelValue, arg) {
973+
if (!this.immutable) return;
967974
if (this.texture.texture === arg.texture) {
968975
const { prevArg } = kernelValue;
969976
if (prevArg) {

0 commit comments

Comments
 (0)