Skip to content

Commit 03972cc

Browse files
fix: #553 call gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false); on every texture type and add unit tests
fix: Framebuffer loss after texture is deleted fix: Split up array and primitive (index.js) types of KernelValues and introduce .setup() * This was needed to handle .toArray() from the fix from #553 fix: Performance fix, define texture types in `kernelValue.setup()`, rather than on every `kernelValue.updateValue()`
1 parent 316e35a commit 03972cc

37 files changed

+914
-764
lines changed

dist/gpu-browser-core.js

Lines changed: 244 additions & 278 deletions
Large diffs are not rendered by default.

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: 244 additions & 278 deletions
Large diffs are not rendered by default.

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.

package-lock.json

Lines changed: 1 addition & 1 deletion
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.4.6",
3+
"version": "2.4.7",
44
"description": "GPU Accelerated JavaScript",
55
"engines": {
66
"node": ">=8.0.0"

src/backend/gl/kernel-string.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,7 @@ function getToArrayString(kernelResult, textureName) {
321321
*/
322322
function findKernelValue(argument, kernelValues, values, context, uploadedValues) {
323323
if (argument === null) return null;
324+
if (kernelValues === null) return null;
324325
switch (typeof argument) {
325326
case 'boolean':
326327
case 'number':

src/backend/gl/texture/index.js

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,24 +24,26 @@ class GLTexture extends Texture {
2424
}
2525
}
2626

27+
/**
28+
* @private
29+
*/
2730
cloneTexture() {
2831
this.texture._refs--;
2932
const { context: gl, size, texture } = this;
3033
const existingFramebuffer = gl.getParameter(gl.FRAMEBUFFER_BINDING);
31-
if (!texture._framebuffer) {
32-
texture._framebuffer = gl.createFramebuffer();
34+
if (!this._framebuffer) {
35+
this._framebuffer = gl.createFramebuffer();
3336
}
34-
texture._framebuffer.width = size[0];
35-
texture._framebuffer.width = size[1];
36-
gl.bindFramebuffer(gl.FRAMEBUFFER, texture._framebuffer);
37+
this._framebuffer.width = size[0];
38+
this._framebuffer.height = size[1];
39+
gl.bindFramebuffer(gl.FRAMEBUFFER, this._framebuffer);
3740
selectTexture(gl, texture);
3841
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
3942
const target = gl.createTexture();
4043
selectTexture(gl, target);
4144
gl.texImage2D(gl.TEXTURE_2D, 0, this.internalFormat, size[0], size[1], 0, this.textureFormat, this.textureType, null);
4245
gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, size[0], size[1]);
4346
target._refs = 1;
44-
target._framebuffer = texture._framebuffer;
4547
this.texture = target;
4648
if (existingFramebuffer) {
4749
gl.bindFramebuffer(gl.FRAMEBUFFER, existingFramebuffer);
@@ -50,8 +52,9 @@ class GLTexture extends Texture {
5052

5153
delete() {
5254
super.delete();
53-
if (this.texture._refs === 0 && this.texture._framebuffer) {
54-
this.context.deleteFramebuffer(this.texture._framebuffer);
55+
if (this.texture._refs === 0 && this._framebuffer) {
56+
this.context.deleteFramebuffer(this._framebuffer);
57+
this._framebuffer = null;
5558
}
5659
}
5760
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
const { WebGLKernelValue } = require('./index');
2+
const { Input } = require('../../../input');
3+
4+
/**
5+
* @abstract
6+
*/
7+
class WebGLKernelArray extends WebGLKernelValue {
8+
/**
9+
*
10+
* @param {number} width
11+
* @param {number} height
12+
*/
13+
checkSize(width, height) {
14+
if (!this.kernel.validate) return;
15+
const { maxTextureSize } = this.kernel.constructor.features;
16+
if (width > maxTextureSize || height > maxTextureSize) {
17+
if (width > height) {
18+
throw new Error(`Argument width of ${width} larger than maximum size of ${maxTextureSize} for your GPU`);
19+
} else {
20+
throw new Error(`Argument height of ${height} larger than maximum size of ${maxTextureSize} for your GPU`);
21+
}
22+
}
23+
}
24+
25+
setup() {
26+
this.requestTexture();
27+
this.setupTexture();
28+
this.defineTexture();
29+
}
30+
31+
requestTexture() {
32+
this.texture = this.onRequestTexture();
33+
}
34+
35+
defineTexture() {
36+
const { context: gl } = this;
37+
gl.activeTexture(this.contextHandle);
38+
gl.bindTexture(gl.TEXTURE_2D, this.texture);
39+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
40+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
41+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
42+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
43+
}
44+
45+
setupTexture() {
46+
this.contextHandle = this.onRequestContextHandle();
47+
this.index = this.onRequestIndex();
48+
this.dimensionsId = this.id + 'Dim';
49+
this.sizeId = this.id + 'Size';
50+
}
51+
52+
/**
53+
* bit storage ratio of source to target 'buffer', i.e. if 8bit array -> 32bit tex = 4
54+
* @param value
55+
* @returns {number}
56+
*/
57+
getBitRatio(value) {
58+
if (Array.isArray(value[0])) {
59+
return this.getBitRatio(value[0]);
60+
} else if (value.constructor === Input) {
61+
return this.getBitRatio(value.value);
62+
}
63+
switch (value.constructor) {
64+
case Uint8ClampedArray:
65+
case Uint8Array:
66+
case Int8Array:
67+
return 1;
68+
case Uint16Array:
69+
case Int16Array:
70+
return 2;
71+
case Float32Array:
72+
case Int32Array:
73+
default:
74+
return 4;
75+
}
76+
}
77+
78+
destroy() {
79+
if (this.prevArg) {
80+
this.prevArg.delete();
81+
}
82+
this.context.deleteTexture(this.texture);
83+
}
84+
}
85+
86+
module.exports = {
87+
WebGLKernelArray
88+
};

src/backend/web-gl/kernel-value/html-image.js

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,12 @@
11
const { utils } = require('../../../utils');
2-
const { WebGLKernelValue } = require('./index');
2+
const { WebGLKernelArray } = require('./array');
33

4-
class WebGLKernelValueHTMLImage extends WebGLKernelValue {
4+
class WebGLKernelValueHTMLImage extends WebGLKernelArray {
55
constructor(value, settings) {
66
super(value, settings);
77
const { width, height } = value;
88
this.checkSize(width, height);
99
this.dimensions = [width, height, 1];
10-
this.requestTexture();
1110
this.textureSize = [width, height];
1211
this.uploadValue = value;
1312
}
@@ -32,10 +31,6 @@ class WebGLKernelValueHTMLImage extends WebGLKernelValue {
3231
const { context: gl } = this;
3332
gl.activeTexture(this.contextHandle);
3433
gl.bindTexture(gl.TEXTURE_2D, this.texture);
35-
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
36-
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
37-
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
38-
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
3934
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
4035
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this.uploadValue = inputImage);
4136
this.kernel.setUniform1i(this.id, this.index);

0 commit comments

Comments
 (0)