Skip to content
This repository was archived by the owner on Jul 5, 2020. It is now read-only.

Commit 2dc2115

Browse files
authored
Add files via upload
1 parent a334e0a commit 2dc2115

File tree

1 file changed

+171
-0
lines changed

1 file changed

+171
-0
lines changed

turbo.js

+171
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
(function() {
2+
// turbo.js
3+
// (c) turbo - github.com/turbo
4+
// MIT licensed
5+
"use strict";
6+
7+
var gl = document.createElement('canvas').getContext('experimental-webgl', {alpha : false, antialias : false});
8+
9+
// turbo.js requires a 32bit float vec4 texture. Some systems only provide 8bit/float
10+
// textures. A workaround is being created, but turbo.js shouldn't be used on those
11+
// systems anyway.
12+
if (!gl.getExtension('OES_texture_float'))
13+
throw new Error('turbojs requires OES_texture_float extension.');
14+
15+
// GPU texture buffer from JS typed array
16+
function newBuffer(data, f, e) {
17+
var buf = gl.createBuffer();
18+
19+
gl.bindBuffer((e || gl.ARRAY_BUFFER), buf);
20+
gl.bufferData((e || gl.ARRAY_BUFFER), new (f || Float32Array)(data), gl.STATIC_DRAW);
21+
22+
return buf;
23+
}
24+
25+
var positionBuffer = newBuffer([ -1, -1, 1, -1, 1, 1, -1, 1 ]);
26+
var textureBuffer = newBuffer([ 0, 0, 1, 0, 1, 1, 0, 1 ]);
27+
var indexBuffer = newBuffer([ 1, 2, 0, 3, 0, 2 ], Uint16Array, gl.ELEMENT_ARRAY_BUFFER);
28+
29+
var vertexShaderCode =
30+
"attribute vec2 position;\n" +
31+
"varying vec2 pos;\n" +
32+
"attribute vec2 texture;\n" +
33+
"\n" +
34+
"void main(void) {\n" +
35+
" pos = texture;\n" +
36+
" gl_Position = vec4(position.xy, 0.0, 1.0);\n" +
37+
"}"
38+
39+
var stdlib =
40+
"\n" +
41+
"precision mediump float;\n" +
42+
"uniform sampler2D u_texture;\n" +
43+
"varying vec2 pos;\n" +
44+
"\n" +
45+
"vec4 read(void) {\n" +
46+
" return texture2D(u_texture, pos);\n" +
47+
"}\n" +
48+
"\n" +
49+
"void commit(vec4 val) {\n" +
50+
" gl_FragColor = val;\n" +
51+
"}\n" +
52+
"\n" +
53+
"// user code begins here\n" +
54+
"\n"
55+
56+
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
57+
58+
gl.shaderSource(vertexShader, vertexShaderCode);
59+
gl.compileShader(vertexShader);
60+
61+
// This should not fail.
62+
if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS))
63+
throw new Error(
64+
"\nERROR: Could not build internal vertex shader (fatal).\n" + "\n" +
65+
"INFO: >REPORT< THIS. That's our fault!\n" + "\n" +
66+
"--- CODE DUMP ---\n" + vertexShaderCode + "\n\n" +
67+
"--- ERROR LOG ---\n" + gl.getShaderInfoLog(vertexShader)
68+
);
69+
70+
// Transfer data onto clamped texture and turn off any filtering
71+
function createTexture(data, size) {
72+
var texture = gl.createTexture();
73+
74+
gl.bindTexture(gl.TEXTURE_2D, texture);
75+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
76+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
77+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
78+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
79+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, size, size, 0, gl.RGBA, gl.FLOAT, data);
80+
gl.bindTexture(gl.TEXTURE_2D, null);
81+
82+
return texture;
83+
}
84+
85+
window.turbojs = {
86+
// run code against a pre-allocated array
87+
run : function(ipt, code) {
88+
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
89+
90+
gl.shaderSource(
91+
fragmentShader,
92+
stdlib + code
93+
);
94+
95+
gl.compileShader(fragmentShader);
96+
97+
// Use this output to debug the shader
98+
// Keep in mind that WebGL GLSL is **much** stricter than e.g. OpenGL GLSL
99+
if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
100+
var LOC = code.split('\n');
101+
var dbgMsg = "ERROR: Could not build shader (fatal).\n\n------------------ KERNEL CODE DUMP ------------------\n"
102+
103+
for (var nl = 0; nl < LOC.length; nl++)
104+
dbgMsg += (stdlib.split('\n').length + nl) + "> " + LOC[nl] + "\n";
105+
106+
dbgMsg += "\n--------------------- ERROR LOG ---------------------\n" + gl.getShaderInfoLog(fragmentShader)
107+
108+
throw new Error(dbgMsg);
109+
}
110+
111+
var program = gl.createProgram();
112+
113+
gl.attachShader(program, vertexShader);
114+
gl.attachShader(program, fragmentShader);
115+
gl.linkProgram(program);
116+
117+
if (!gl.getProgramParameter(program, gl.LINK_STATUS))
118+
throw new Error('ERROR: Could not initialize shaders (fatal).\n');
119+
120+
var uTexture = gl.getUniformLocation(program, 'u_texture');
121+
var aPosition = gl.getAttribLocation(program, 'position');
122+
var aTexture = gl.getAttribLocation(program, 'texture');
123+
124+
gl.useProgram(program);
125+
126+
var size = Math.sqrt(ipt.data.length) / 4;
127+
var texture = createTexture(ipt.data, size);
128+
129+
gl.viewport(0, 0, size, size);
130+
gl.bindFramebuffer(gl.FRAMEBUFFER, gl.createFramebuffer());
131+
132+
// Types arrays speed this up tremendously.
133+
var nTexture = createTexture(new Float32Array(ipt.data.length), size);
134+
135+
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, nTexture, 0);
136+
137+
var frameBufferStatus = (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE);
138+
139+
if (!frameBufferStatus)
140+
throw new Error('ERROR: (fatal): ' + frameBufferStatus.message);
141+
142+
gl.bindTexture(gl.TEXTURE_2D, texture);
143+
gl.activeTexture(gl.TEXTURE0);
144+
gl.uniform1i(uTexture, 0);
145+
gl.bindBuffer(gl.ARRAY_BUFFER, textureBuffer);
146+
gl.enableVertexAttribArray(aTexture);
147+
gl.vertexAttribPointer(aTexture, 2, gl.FLOAT, false, 0, 0);
148+
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
149+
gl.enableVertexAttribArray(aPosition);
150+
gl.vertexAttribPointer(aPosition, 2, gl.FLOAT, false, 0, 0);
151+
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer);
152+
gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0);
153+
gl.readPixels(0, 0, size, size, gl.RGBA, gl.FLOAT, ipt.data);
154+
// ^ 4 x 32 bit ^
155+
156+
return ipt.data.subarray(0, ipt.length);
157+
},
158+
alloc: function(sz) {
159+
// A sane limit for most GPUs out there.
160+
// JS falls apart before GLSL limits could ever be reached.
161+
if (sz > 16777216)
162+
throw new Error("Whoops, the maximum array size is exceeded!");
163+
164+
var ns = Math.pow(Math.pow(2, Math.ceil(Math.log(sz) / 1.386) - 1), 2);
165+
return {
166+
data : new Float32Array(ns * 16),
167+
length : sz
168+
};
169+
}
170+
};
171+
})();

0 commit comments

Comments
 (0)