|8.1.2010||The year I started blogging (blogware)|
|9.1.2010||Linux initramfs with iSCSI and bonding support for PXE booting|
|9.1.2010||Using manually tweaked PTX assembly in your CUDA 2 program|
|9.1.2010||OpenCL autoconf m4 macro|
|9.1.2010||Mandelbrot with MPI|
|10.1.2010||Using dynamic libraries for modular client threads|
|11.1.2010||Creating an OpenGL 3 context with GLX|
|11.1.2010||Creating a double buffered X window with the DBE X extension|
|12.1.2010||A simple random file read benchmark|
|14.12.2011||Change local passwords via RoundCube safer|
|5.1.2012||Multi-GPU CUDA stress test|
|6.1.2012||CUDA (Driver API) + nvcc autoconf macro|
|29.5.2012||CUDA (or OpenGL) video capture in Linux|
|31.7.2012||GPGPU abstraction framework (CUDA/OpenCL + OpenGL)|
|7.8.2012||OpenGL (4.3) compute shader example|
|10.12.2012||GPGPU face-off: K20 vs 7970 vs GTX680 vs M2050 vs GTX580|
|4.8.2013||DAViCal with Windows Phone 8 GDR2|
|5.5.2015||Sample pattern generator|
The important thing to note is that while the other shaders have a fixed execution order, compute shaders can essentially alter any data anywhere. Shader objects within a program object are implicitly pipelined after another, and a program object is "ready to go" as it is. Compute shaders cannot be baked into a program object alongside other shaders as their execution order is not fixed. Instead, compute shaders have to be placed into program objects by themselves and the application has to instruct OpenGL about the execution order explicitly by switching on and off the compute shader program object and calling DispatchCompute*() to run the compute shaders.
OpenGL compute shaders are GLSL and similar to other shaders: you can read textures, images, and buffers and write images and buffers. Just like with other GPGPU implementations, threads are grouped into work groups and one compute shader invocation processes a bunch of work groups. The work group size is specified along with the kernel source code, and the number of work groups launched is given by the application as arguments to DispatchCompute*().
You should know when to choose a compute shader over the other shaders for your algorithm (this is not one such example). The reasons to use GPGPU are universal and have nothing to do with OpenGL compute shaders specifically.
You can grab the full example program here, but the important files are main.cpp and opengl_cs.cpp. In main.cpp we create an OpenGL 4.3 context (I'm being strict and using a forward-compatible core profile, but you don't have to), a texture for the compute shader to write and the fragment shader to read, and two program objects. One object is for the compute shader and the other is for rendering (vertex + fragment shaders). After that we go into a loop where we update a counter in the compute shader, fill in the texture (as image2D), and blit the texture onto the screen.
The compute shader set-up should look familiar as it's just another shader. (There are some specifics which are documented in the GLSLang specification.)
Great article, thanks!!!- Rich
Thank you very much!- Aavci
Nice! Thank you!- linsnos
Why do you set texHandle as arg of genRenderProg() and genRenderProg()? You havent even use it internally. I don't know how it supposed to work it that way...- Wonderer
Oh yeah you're right; I'm not using the parameter, so it's ignored. There's no need to use it since it's bound to GL_TEXTURE0 during creation and kept bound throughout the program.- wili
Very helpful !! -agb- AB
to anyone having problems compiling/running this with a nvidia card, try -L/usr/lib/nvidia-xxx with g++ (xxx being your driver version) and change "uniform image2D destTex" in the shader code to "writeonly uniform image2D destTex"- meepo
thank you @meepo- nozam
Thank you! This was easy to duplicate. Well done.- freeflyclone