nclgl
July 19 2018
Native version of GPGPU Javascript library (WEBASM)WebCLGL (+ WebASM)
NCLGL use WebGL2 specification to interpret code.
First version of algorithm was created in 2013 (hosted on Google Code). On this, WebGL is used like OpenCL for GPGPU calculus using the traditional Render To Texture technique.
Features:
- Basic numerical calculus on GPU.
- WebGL graphics allowing write multiple shaders, interconnect and save arguments.
- NCLGL handle any WebGL operation preparing all neccesary resources (buffers and programs initialization, vertex/fragment programs buffers interconnection, Renders to texture, etc... reducing time to write any advanced shaders.
API Doc WebCLGL
WebGL 2.0 API Quick Reference Guide
WebASM
Installation
npm install nclgl
import "nclgl";
OR BROWSER:
<script src="/dist/nclgl/NCLGL.class.js"></script>
<script src="/dist/nclgl/nclgl.js"></script>
Simple A+B
// TYPICAL A + B WITH CPU
var arrayResult = [];
for(var n = 0; n < _length; n++) {
var sum = arrayA[n]+arrayB[n];
arrayResult[n] = sum;
}
// PERFORM A + B WITH GPU
window.addEventListener("nclgl", () => {
gpufor_asm({"float* A": arrayA, "float* B": arrayB}, "n",
"float sum = A[n]+B[n];"+
"return sum;", function(result) {
document.getElementById('DIVC_GPU').innerText = result.join();
});
});
Previous examples only execute one program type "KERNEL" (fragment program), write to a hidden buffer "result", perform readPixels over this buffer and return the output. Graphical output
To represent data that evolve over time you can enable the graphical output indicating one WebGLRenderingContext or canvas element as first argument:
<canvas id="graph" width="512" height="512"></canvas>
var tick = function(gpufG) {
window.requestAnimFrame(tick.bind(null, gpufG));
gpufG.processKernels();
gpufG.clearContext();
//gpufG.setArg("pole1X", 30);
gpufG.processGraphic("posXYZW");
};
window.addEventListener("nclgl", () => {
new gpufor_asm( document.getElementById("graph"), // canvas or existings WebGL context
{"float4* posXYZW": arrayNodePosXYZW,
"float4* dir": arrayNodeDir,
"float*attr nodeId": arrayNodeId,
"mat4 PMatrix": transpose(getProyection()),
"mat4 cameraWMatrix": transpose(new Float32Array([ 1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, -100.0,
0.0, 0.0, 0.0, 1.0])),
"mat4 nodeWMatrix": transpose(new Float32Array([1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0]))},
// KERNEL PROGRAM (update "dir" & "posXYZW" in return instruction)
{"type": "KERNEL",
"name": "PROG_KERNEL",
"viewSource": false,
"config": ["n", ["dir","posXYZW"],
// head
'',
// source
'vec3 currentPos = posXYZW[n].xyz;'+
'vec3 newDir = dir[n].xyz*0.995;'+
'return [vec4(newDir,0.0), vec4(currentPos,1.0)+vec4(newDir,0.0)];'],
"depthTest": true,
"blend": false,
"blendEquation": "FUNC_ADD",
"blendSrcMode": "SRC_ALPHA",
"blendDstMode": "ONE_MINUS_SRC_ALPHA"},
// GRAPHIC PROGRAM
{"type": "GRAPHIC",
"name": "PROG_GRAPHIC",
"viewSource": false,
"config": [ // vertex head
'',
// vertex source
'vec2 xx = get_global_id(nodeId[], uBufferWidth, 1.0);'+
'vec4 nodePosition = posXYZW[xx];'+ // now use the updated posXYZW
'mat4 nodepos = nodeWMatrix;'+
'nodepos[3][0] = nodePosition.x;'+
'nodepos[3][1] = nodePosition.y;'+
'nodepos[3][2] = nodePosition.z;'+
'gl_Position = PMatrix * cameraWMatrix * nodepos * vec4(1.0, 1.0, 1.0, 1.0);'+
'gl_PointSize = 2.0;',
// fragment head
'',
// fragment source
'return vec4(1.0, 1.0, 1.0, 1.0);' // color
],
"drawMode": 4,
"depthTest": true,
"blend": false,
"blendEquation": "FUNC_ADD",
"blendSrcMode": "SRC_ALPHA",
"blendDstMode": "ONE_MINUS_SRC_ALPHA"}
, tick);
});
Compilation
emcc $Projectpath$/src/nclgl/main.cpp $Projectpath$/src/nclgl/NCLGLmanager.cpp $Projectpath$/src/nclgl/NCLGLFor.cpp $Projectpath$/src/nclgl/NCLGL.cpp $Projectpath$/src/nclgl/NCLGLKernel.cpp $Projectpath$/src/nclgl/NCLGLVertexFragmentProgram.cpp $Projectpath$/src/nclgl/NCLGLPgrInValue.cpp $Projectpath$/src/nclgl/NCLGLBuffer.cpp $Projectpath$/src/nclgl/NCLGLArgValue.cpp $Projectpath$/src/nclgl/NCLGLUtils.cpp -I$Projectpath$/include/ -I$Projectpath$/include/nclgl/ -O3 -s "EXPORTED_FUNCTIONS=['_main', '_free']" -s "EXTRA_EXPORTED_RUNTIME_METHODS=['ccall', 'cwrap', 'stringToUTF8']" -g -s ALLOW_MEMORY_GROWTH=1 -s FULL_ES3=1 -s USE_WEBGL2=1 -s WASM=1 -s NO_EXIT_RUNTIME=1 -std=c++1z -o $Projectpath$/dist/nclgl/nclgl.js -DUSE_EMSCRIPTEN=1 -DDEBUG=1
CLI
Simple A+B
cmake-build-release $ ./nclgl "float* A=[0.2,0.2,0.2,0.2,0.1,0.1,0.1,0.1]; float* B=[0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1];" "idx=n" "float sum = A[n]+B[n];return sum;"
[0.300000,0.300000,0.300000,0.300000,0.200000,0.200000,0.200000,0.200000]
Compilation
$ cd nclgl/cmake-build-release
$ cmake -DCMAKE_BUILD_TYPE=Release ..
$ make