WebCL and WebGL

WebCL is an OpenCL extension for Web. It is much more powerful and flexible than WebGL (the last, based on OpenGL ES, is made to support mobile devices with limited resources). WebCL supports e.g.: See also Super-computer in your PC. You need not translators and can write efficient scripts for mighty GPU. Unfortunately, due to its power WebCL may be not safe yet. To use WebCL you need a modern graphical card, OpenCL driver and FireFox with the Nokia Research WebCL extension.

Use this WebCL test to see if your system supports WebCL.

A simple script

You can try the simple parallel random number generator with the kernel
<script id="clRand" type="text/x-opencl">
  __kernel void kRand( global uint* rand ){
    uint x = get_global_id(0);
    rand[x] = 1664525u*rand[x] + 1013904223u;
  }
</script>          
Common for all scripts the loadKernel function reads the kernel source
<script type="text/javascript"> 

function loadKernel ( id ){
   var shaderScript = document.getElementById ( id );
   var str = "";
   var k = shaderScript.firstChild;
   while ( k ){
     if ( k.nodeType == 3 ) str += k.textContent;
     k = k.nextSibling;
   }
   return str;
}
The main function get the WebCL context
function CL_rand () {
  var output = document.getElementById("output");
  output.innerHTML = "";
  try {
    if (window.WebCL == undefined) {
      alert("Unfortunately your system does not support WebCL");
      return false;
    }
    var platforms = WebCL.getPlatformIDs();
    var ctx = WebCL.createContextFromType ([WebCL.CL_CONTEXT_PLATFORM, 
               platforms[0]], WebCL.CL_DEVICE_TYPE_DEFAULT);
    var devices = ctx.getContextInfo(WebCL.CL_CONTEXT_DEVICES);
prepares data
    var n = 8;
    var UIrand = new Uint32Array(n);    
    for ( var i = 0; i < n;  i++)
      UIrand[i] = Math.floor(Math.random() * 4294967295);
    var bufSize = n * 4;
    var bufRand = ctx.createBuffer (WebCL.CL_MEM_READ_WRITE, bufSize);
loads, compiles kernel and set its arguments
    var kernelSrc = loadKernel("clRand");
    var program = ctx.createProgramWithSource(kernelSrc);
    try {
      program.buildProgram ([devices[0]], "");
    } catch(e) {
      alert ("Failed to build WebCL program. Error "
         + program.getProgramBuildInfo (devices[0], 
             WebCL.CL_PROGRAM_BUILD_STATUS) + ":  " 
         + program.getProgramBuildInfo (devices[0], 
             WebCL.CL_PROGRAM_BUILD_LOG));
      throw e;
    }
    var kernel = program.createKernel ("kRand");
    kernel.setKernelArg (0, bufRand);
creates command queue, writes buffer, runs kernel reads and prints result
    var cmdQueue = ctx.createCommandQueue (devices[0], 0);
    
    cmdQueue.enqueueWriteBuffer (bufRand, true, 0, 4*n, UIrand, []);
    cmdQueue.enqueueNDRangeKernel(kernel, 1, [], [n], [n], []);
    cmdQueue.finish();
    cmdQueue.enqueueReadBuffer(bufRand, true, 0, bufSize, UIrand, []);    

    output.innerHTML += "<br>Result = ";
    for (var i = 0; i < n; i = i + 1)
      output.innerHTML += UIrand[i] + ", ";
  } catch(e) {
    document.getElementById("output").innerHTML 
      += "<h3>ERROR:</h3><pre style=\"color:red;\">" + e.message + "</pre>";
    throw e;
  }
}
</script> 
Note that the try block is used to catch WebCL errors. See the Nokia Research WebCL Tutorial for more comments.

Synchronization: Finish, Flush and EventWaitList

To synchronize kernels execution we can use Finish function
  cmdQueue.enqueueNDRangeKernel(kRelax, 2, [], [n,n], [8,8], []);
  cmdQueue.finish();
...
or Flush function and EventWaitList
  var ev = cmdQueue.enqueueNDRangeKernel(kRelax2, 2, [], [n,n], [8,8], []);
  cmdQueue.flush();
  for(var i = 0; i < it; i++){
    kRelax.setKernelArg(0, img0);
    kRelax.setKernelArg(2, img1);
    ev = cmdQueue.enqueueNDRangeKernel(kRelax, 2, [], [n,n], [8,8], [ev]);
    cmdQueue.flush();

    kRelax.setKernelArg(0, img1);
    kRelax.setKernelArg(2, img0);
    ev = cmdQueue.enqueueNDRangeKernel(kRelax, 2, [], [n,n], [8,8], [ev]);
    cmdQueue.flush();
  }
  cmdQueue.enqueueNDRangeKernel(kShow, 2, [], [n,n], [8,8], [ev]);
...
The first construction was ~2 times slower on AMD E-350 processor.

WebCL + WebGL for animation acceleration

In all simulations the kShow kernel calculates array of RGBA pixels. Data are passed to CPU then backwards to GPU as texture. WebGL shader is used to accelerate image drawing (see simple WebGL script cl_gl.js). Simulations in WebCL is notably faster than WebGL based now!
Note that on AMD GPU they work with ANGLE only (I can't use cl_khr_gl_sharing extension yet).

This 2d ink droplet script uses HTML5 Canvas2d to show pictures. It is a litle slower than the script with WebGL based output (fps is 25 and 30 correspondingly).

GPU Gems 3


WebCL Demos
updated   4 Nov 2011