GPGPU C++ library (CLI & WebASM)


Keywords
glsl, gpgpu, gpu, gpu-computing, math, parallel, webassembly, webcl, webgl2
License
MIT
Install
npm install nclgl@1.1.4

Documentation

nclgl

July 19 2018

GPGPU Javascript library (WEBASM)

Native version of 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();
                           });
});

Graphical output

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.
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

Notes

https://github.com/DanRuta/webassembly-webgl-shaders

https://github.com/HarryLovesCode/WebAssembly-WebGL-2