Skip to content

Commit

Permalink
Fixed bug when using the same Buffer for input and output. Added a te…
Browse files Browse the repository at this point in the history
…st/example.
  • Loading branch information
frzi committed Apr 22, 2017
1 parent c6868ad commit fe0b244
Show file tree
Hide file tree
Showing 9 changed files with 172 additions and 22 deletions.
32 changes: 24 additions & 8 deletions dist/blink.js
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,16 @@ const arrayConstructors = new Map([
[UINT8, Uint8Array],
]);


const arrayTypes = new Map([
[Float32Array, FLOAT],
[Int32Array, INT32],
[Int16Array, INT16],
[Int8Array, INT8],
[Uint32Array, UINT32],
[Uint16Array, UINT16],
[Uint8Array, UINT8],
[Uint8ClampedArray, UINT8],
]);


/// Hands out all the types associated with a Buffer's data.
Expand Down Expand Up @@ -215,7 +224,6 @@ class Texture {
gl.readBuffer(gl.COLOR_ATTACHMENT0);
gl.readPixels(0, 0, this.width, this.height, gl[this.format], gl[this.type], data, 0);
});

return true
}
}
Expand Down Expand Up @@ -369,6 +377,7 @@ class DeviceBuffer {
for (const [constructor, type] of arrayTypes) {
if (data instanceof constructor) {
associatedType = type;
break
}
}
}
Expand Down Expand Up @@ -415,7 +424,12 @@ class DeviceBuffer {
data = new typedArray(this.size);
}

this._getReadable().read(data);
// Cast Uint8ClampedArray to Uint8Array.
let ref = data;
if (data instanceof Uint8ClampedArray) {
ref = new Uint8Array(data.buffer);
}
this._getReadable().read(ref);

return data
}
Expand All @@ -427,6 +441,8 @@ class DeviceBuffer {
}

_getReadable(forceCreate = false) {
window.readablesMap = readablesMap;
window.writablesMap = writablesMap;
if (!readablesMap.has(this) && forceCreate) {
const { bytes, internalFormat, format, type } = this.formatInfo;
const [width, height] = this.dimensions;
Expand Down Expand Up @@ -553,9 +569,9 @@ function compileShader(type, source) {

const uniformsFnTable = {
[gl.FLOAT]: 'uniform1f',
[gl.FLOAT_VEC_2]: 'uniform2f',
[gl.FLOAT_VEC_3]: 'uniform3f',
[gl.FLOAT_VEC_4]: 'uniform4f',
[gl.FLOAT_VEC2]: 'uniform2f',
[gl.FLOAT_VEC3]: 'uniform3f',
[gl.FLOAT_VEC4]: 'uniform4f',
[gl.INT]: 'uniform1i',
[gl.INT_VEC2]: 'uniform2i',
[gl.INT_VEC3]: 'uniform3i',
Expand Down Expand Up @@ -750,7 +766,7 @@ class Kernel {
}

// Clean-up all resources.
const allBuffers = [...Object.values(this.inputs), ...Object.values(this.outputs)];
const allBuffers = new Set([...Object.values(this.inputs), ...Object.values(this.outputs)]);
for (const buffer of allBuffers) {
buffer._finish();
}
Expand Down Expand Up @@ -784,7 +800,7 @@ function prepareFragmentShader(inputs, outputDescriptors, source) {
const VERSION = {
major: 0,
minor: 2,
patch: 0,
patch: 2,
toString() { return `${this.major}.${this.minor}.${this.patch}` }
};

Expand Down
2 changes: 1 addition & 1 deletion dist/blink.js.map

Large diffs are not rendered by default.

14 changes: 7 additions & 7 deletions dist/blink.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "blink.js",
"version": "0.2.1",
"version": "0.2.2",
"description": "Easy GPGPU on the web, powered by WebGL 2.0.",
"main": "dist/blink.js",
"homepage": "https://github.com/frzi/blinkjs",
Expand Down
2 changes: 1 addition & 1 deletion src/Buffer.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export class Buffer {
/// Private methods / properties.

get formatInfo() {
for (const [constructor, type] of arrayTypes) {
for (const [constructor, type] of common.arrayTypes) {
if (this.data instanceof constructor) {
return common.formatInfo(type, this.vector)
}
Expand Down
12 changes: 10 additions & 2 deletions src/DeviceBuffer.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,10 @@ export class DeviceBuffer {

let associatedType = type
if (data) {
for (const [constructor, type] of arrayTypes) {
for (const [constructor, type] of common.arrayTypes) {
if (data instanceof constructor) {
associatedType = type
break
}
}
}
Expand Down Expand Up @@ -81,7 +82,12 @@ export class DeviceBuffer {
data = new typedArray(this.size)
}

this._getReadable().read(data)
// Cast Uint8ClampedArray to Uint8Array.
let ref = data
if (data instanceof Uint8ClampedArray) {
ref = new Uint8Array(data.buffer)
}
this._getReadable().read(ref)

return data
}
Expand All @@ -93,6 +99,8 @@ export class DeviceBuffer {
}

_getReadable(forceCreate = false) {
window.readablesMap = readablesMap
window.writablesMap = writablesMap
if (!readablesMap.has(this) && forceCreate) {
const { bytes, internalFormat, format, type } = this.formatInfo
const [width, height] = this.dimensions
Expand Down
2 changes: 1 addition & 1 deletion src/Kernel.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ export class Kernel {
}

// Clean-up all resources.
const allBuffers = [...Object.values(this.inputs), ...Object.values(this.outputs)]
const allBuffers = new Set([...Object.values(this.inputs), ...Object.values(this.outputs)])
for (const buffer of allBuffers) {
buffer._finish()
}
Expand Down
1 change: 0 additions & 1 deletion src/WebGL/Texture.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ export class Texture {
gl.readBuffer(gl.COLOR_ATTACHMENT0)
gl.readPixels(0, 0, this.width, this.height, gl[this.format], gl[this.type], data, 0)
})

return true
}
}
Expand Down
127 changes: 127 additions & 0 deletions test/canvas_greyscale.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
<!doctype html>
<html>
<head>
<title>Greyscale</title>
<style>
body {font-family:sans-serif;}
div {float:left; margin:10px;}
canvas, button, span {display:block;}
button, span {width:400px; padding:4px 0; margin-top:20px;}
</style>
<script src="../dist/blink.js"></script>
</head>
<body>
<script>
const kernelSource = `
void main() {
highp uvec4 color = texture(in_color, bl_UV);
highp uint grey = (color.r + color.g + color.b) / 3u;
out_color = uvec4(grey, grey, grey, color.a);
}`


makeTest('Buffer', function (ctx) {
// Get the canvas data.
let imageData = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height)

// Create buffer.
let buffer = new blink.Buffer({
data: imageData.data,
vector: 4
})

let kernel = new blink.Kernel({
input: { in_color: buffer },
output: { out_color: buffer }
}, kernelSource)

kernel.exec()

ctx.putImageData(imageData, 0, 0)

// Clean up.
kernel.delete()
})

makeTest('DeviceBuffer', function (ctx) {
let imageData = ctx.getImageData(0, 0, ctx.canvas.width, ctx.canvas.height)

let buffer = new blink.DeviceBuffer({
data: imageData.data,
vector: 4
})

let kernel = new blink.Kernel({
input: { in_color: buffer },
output: { out_color: buffer }
}, kernelSource)

kernel.exec()

// Download to the original ImageData object.
buffer.toHost(imageData.data)

ctx.putImageData(imageData, 0, 0)

// Clean up.
kernel.delete()
buffer.delete()
})


function makeTest(title, onClick) {
let div = document.createElement('div')

let h1 = document.createElement('h1')
h1.textContent = title
div.appendChild(h1)

let canvas = document.createElement('canvas')
canvas.width = canvas.height = 400
div.appendChild(canvas)

let rect = [0, 0, canvas.width, canvas.height]

// Draw on the canvas.
const ctx = canvas.getContext('2d')
let gradient = ctx.createLinearGradient(0, 0, 0, canvas.height)
gradient.addColorStop(0, 'rgb(255, 0, 0)')
gradient.addColorStop(0.2, 'rgb(255, 255, 0)')
gradient.addColorStop(0.4, 'rgb(0, 255, 0)')
gradient.addColorStop(0.6, 'rgb(0, 255, 255)')
gradient.addColorStop(0.8, 'rgb(0, 0, 255)')
gradient.addColorStop(1, 'rgb(255, 0, 255)')
ctx.fillStyle = gradient
ctx.fillRect(...rect)

const text = `blink.js ${blink.VERSION}`
ctx.fillStyle = 'rgb(0, 255, 0)'
ctx.font = '50px sans-serif'
ctx.textAlign = 'center'
ctx.textBaseline = 'top'
ctx.lineWidth = 4
ctx.strokeStyle = 'white'
ctx.strokeText(text, canvas.width / 2, (canvas.height - 50) / 2)
ctx.fillText(text, canvas.width / 2, (canvas.height - 50) / 2)

// Button.
let button = document.createElement('button')
button.textContent = 'Greyscale'

button.addEventListener('click', function () {
let then = performance.now()
onClick(ctx)
button.remove()
span.textContent = `${performance.now() - then} ms`
})

div.appendChild(button)

let span = document.createElement('span')
div.appendChild(span)

document.body.appendChild(div)
}
</script>
</body>
</html>

0 comments on commit fe0b244

Please sign in to comment.