How to use CLEW

OpenCL Extension Wrangler Library (CLEW) does to OpenCL what GLEW does to OpenGL. It takes out all the pain of dealing with OpenCL libraries from different vendors and on different platforms. The best part is that your code will compile and run even on a computer without a OpenCL device or library. Only when it calls a OpenCL call does it fail.

  • Get the CLEW code from Github:
$ git clone https://github.com/martijnberger/clew.git
  • Compile CLEW:
$ mkdir build
$ cd build
$ cmake ..
$ make
  • Test if CLEW works:
$ clewTest/clewTest
num platforms: 1

If you have an OpenCL device and OpenCL library installed, then the number of platforms reported will be greater than zero.

  • For your own code, include the clew.h header file and link with the libclew.so library file. Call clewInit at the beginning. After that you can follow with any OpenCL calls.

Tried with: NVIDIA 352 drivers, NVIDIA GeForce GTX 750 Ti and Ubuntu 14.04

Advertisements

glCapsViewer

20151013_glcapsviewer

I discovered glCapsViewer recently while doing OpenGL programming. Typically, you will need to check which OpenGL capabilities are available on the GPU and driver of your system.

The common ways to check this is using glxinfo on the commandline or from the NVIDIA X Server Settings application. Neither of these provides an user-friendly way to browse through the capabilities.

glCapsViewer aims to provide such an user-friendly interface to view all the OpenGL capabilities of your GPU and driver. It is also connected to an online database to which you can upload the capabilities of your system easily.

Install

I could not find a package for Ubuntu and the old compiled archive provided for Linux did not work for me. So, I compiled glCapsViewer from source, which is easy:

  • Make sure you have Qt5 headers and libraries installed:
$ sudo apt install qtbase5-dev
  • Download and build the program:
$ git clone https://github.com/SaschaWillems/glCapsViewer.git
$ cd glCapsViewer
$ mkdir build
$ cd build
$ cmake ..
$ make
  • Move back the program to directory containing XML files that it needs and run it:
$ cd ..
$ mv build/glcapsviewer .
$ ./glcapsviewer

Tried with: Qt 5.2.1 and Ubuntu 14.04

OpenGL functions not resolved in Eclipse

Problem

In Eclipse, I am able to build and run C++ code that calls OpenGL functions. However, most of the OpenGL calls are marked as could not be resolved by the Indexer in Eclipse.

Solution

Almost all of the modern OpenGL functions are defined behind the GL_GLEXT_PROTOTYPES symbol in header files such as gl.h and glext.h. We need to define this symbol for the Indexer.

Go to project Properties -> C/C++ General -> Paths and Symbols. Under the Symbols tab, add a new symbol with the Name as GL_GLEXT_PROTOTYPES. No value needs to be provided. Rebuild the index for the project and the unresolved indications for OpenGL functions should be gone!

Tried with: Eclipse 4.5 and Ubuntu 14.04

How to update Mesa

Mesa is the open source library on Linux that provides the OpenGL implementation for programs. The Mesa library installed by Ubuntu can be pretty old. For example, my Mesa library showed support for the archaic OpenGL 2.1 standard.

Thankfully, there is a PPA that provides updated Mesa libraries. Updating is easy:

$ sudo add-apt-repository ppa:oibaf/graphics-drivers
$ sudo apt-get update
$ sudo apt-get dist-upgrade

Remember to reboot the computer after this update. I found that Mesa supported OpenGL 3.0 after this update! 😄

Tried with: Mesa 11.1 and Ubuntu 14.04

Skype error on libGL shared library

Problem

I installed Skype from here using the package for Ubuntu 12.04 Multiarch. When I ran Skype from the Dash, nothing happened. When I ran Skype from the shell, I found that it quit with this error:

$ skype
skype: error while loading shared libraries: libGL.so.1: cannot open shared object file: No such file or directory

Solution

  • Let us check the shared library dependencies of this Skype executable. This actually uses the dynamic linker and loader to compare what is required by the executable with what shared libraries are available in the cache:
$ ldd /usr/bin/skype | grep libGL
libGL.so.1 => not found
libGL.so.1 => not found

So yes, the shared library file is not found.

  • I first checked if the libGL.so.1 was available in the shared library cache:
$ ldconfig -p | grep libGL.so.1
libGL.so.1 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/mesa/libGL.so.1

So, a 64-bit shared library of the required name was present in the cache!

  • I next checked the Skype program itself:
$ file /usr/bin/skype
/usr/bin/skype: ELF 32-bit LSB  shared object, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, stripped

This was a 32-bit executable. Might it require a 32-bit shared library and could this be causing the problem?

  • The 32-bit GL library files and directories updated in cache are controlled by the configuration in /etc/ld.so.conf.d/i386-linux-gnu_GL.conf. This in turn can be easily switched between libraries provided by different providers using update-alternatives:
$ sudo update-alternatives --config i386-linux-gnu_gl_conf

I found that currently the GL library files provided by /usr/lib/nvidia-352/alt_ld.so.conf, that is, by my NVIDIA drivers was being used. I picked the /usr/lib/i386-linux-gnu/mesa/ld.so.conf which is by MESA. This only sets the symbolic link for the /etc/ld.so.conf.d/i386-linux-gnu_GL.conf from the NVIDIA conf file to the MESA conf file.

  • Next we update the cache so that the NVIDIA library files are removed and the MESA library files are symbolically linked to as the default GL library files:
$ sudo ldconfig
  • Let us check what the cache holds now:
$ ldconfig -p | grep libGL.so.1
libGL.so.1 (libc6,x86-64) => /usr/lib/x86_64-linux-gnu/mesa/libGL.so.1
libGL.so.1 (libc6) => /usr/lib/i386-linux-gnu/mesa/libGL.so.1

We can see that we now have an additional entry, which has no architecture specified, but it is for 32-bit by default.

  • Finally, let us check if the shared dependencies of the Skype exectuable are met now:
$ ldd /usr/bin/skype | grep libGL
libGL.so.1 => /usr/lib/i386-linux-gnu/mesa/libGL.so.1 (0xf16b5000)

Yes, they are! I ran Skype after this and it worked fine! 😄

Tried with: Skype 4.3 (multiarch) and Ubuntu 14.04

How to check error in OpenGL

In OpenGL, multiple types of errors might have occurred by the time you check for them. The errors are stored using the data type GLenum. GL_NO_ERROR always has the value 0 and you need to call glGetError() multiple times (one for each error that has occurred) until it returns GL_NO_ERROR. A general rule of thumb is to check for error at least once in a rendering cycle.

The standard OpenGL errors I found defined on my system:

#define GL_NO_ERROR                0
#define GL_INVALID_ENUM                0x0500
#define GL_INVALID_VALUE           0x0501
#define GL_INVALID_OPERATION           0x0502
#define GL_STACK_OVERFLOW          0x0503
#define GL_STACK_UNDERFLOW         0x0504
#define GL_OUT_OF_MEMORY           0x0505

In addition to these standard values, OpenGL extensions could introduce their own error types.

Putting all this together, we can write a simple function named CheckGLError that checks for errors and if any, then prints them out:

Note: If you are using GLU, then the gluErrorString function can be used to convert OpenGL error to a string.

Tried with: Mesa 10.1.3 and Ubuntu 14.04

How to register class method as C callback

Problem

A typical problem when using a C library with your own C++ code: the library requires a C callback function pointer, but you want to pass your C++ class method (that is non-static) to it.

I face this problem when using C libraries like GLFW or GLUT, which provide an interface to OpenGL, which is also a C library. For example, say I want to register a C++ class method with GLFW as callback for mouse button event. GLFW expects me to pass it a C function pointer with this signature:

void ButtonCallback(GLFWwindow*, int, int, int);

// Register above function as callback
glfwSetMouseButtonCallback(window, ButtonCallback);

I want to register this C++ class method as the callback:

class Foo
{
public:
    Foo()
    {
        // Error!
        glfwSetMouseButtonCallback(window, FooButtonCallback);
    }

    void FooButtonCallback(GLFWwindow*, int, int, int)
    { /* something */ }
};

No pointer trickery can make it work because the signature of a C++ class non-static method is different from a C callback.

Solution

One solution is to only use C++ class static methods as callback. These can be passed as C callback because these are nothing but C functions with a glorified name. However, this causes serious problems later when you want update some class variable with the data received from the callback.

The solution I use in such a scenario is an ugly hack called trampoline. The idea is to create a global C function which can be passed as callback and inside it call the C++ method by using its object pointer:

Foo* g_foo_ptr = nullptr;
void TrampButtonCallback(GLFWwindow* a, int b, int c, int d)
{
    if (g_foo_ptr) // Check before calling
        g_foo_ptr->FooButtonCallback(a, b, c, d);
}

class Foo
{
public:
    Foo()
    {
        g_foo_ptr = this; // Store global
        glfwSetMouseButtonCallback(window, TrampButtonCallback);
    }

    void FooButtonCallback(GLFWwindow*, int, int, int)
    { /* something */ }
};

OpenGL Mathematics (GLM) Library

OpenGL Mathematics (GLM) is a library of mathematics primitives and functions that can be useful in OpenGL, shader, CUDA and other graphics related code. Everyone ends up writing their own version of this code, often with errors and waste of time. GLM could be a good choice in such cases. Note that GLM is not as featured or complex as Eigen.

Briefly, here are the types and operations you can get in GLM:

  • vec3, vec4
  • mat3, mat4
  • Vector operations like normalize, bit swizzling
  • Matrix operations
  • Use of matrices for projection and lighting operations

Installing GLM library is easy:

$ sudo apt install libglm-dev

GLM is a template header library. So, no library file needs to be specified for the linking stage of compilation.

Segmentation fault at glCreateShader in wxWidgets

Problem

I had a simple graphics program written using OpenGL and using GLUT for windowing. To get more windowing functionality, I wanted to move it to wxWidgets. I picked an example program that uses OpenGL in wxWidgets. It compiled and worked correctly. When I placed my OpenGL code into this example, I got a segmentation fault at the glCreateShader call in my code.

Solution

I had a glewInit in my original code. I had put this in the application class constructor. Apparently, wxWidgets requires that the first OpenGL or GLEW call be placed inside the OnPaint event handler function. Look for EVT_PAINT to find this function. Once I did that, the error disappeared and OpenGL worked.

Inconsistency error with libGL.so

Problem

I compiled and linked an OpenGL program with -lGL. On executing the program, I got this runtime error:

Inconsistency detected by ld.so: dl-version.c: 224: _dl_check_map_versions: Assertion `needed != ((void *)0)' failed!

Solution

The cryptic error message held some clues. I guessed there was some inconsistency between the various shared library files being linked into the program.

Searching for the OpenGL library gave multiple results:

$ locate libGL.so
/usr/lib/nvidia-331/libGL.so
/usr/lib/nvidia-331/libGL.so.1
/usr/lib/nvidia-331/libGL.so.331.38
/usr/lib/x86_64-linux-gnu/libGL.so
/usr/lib/x86_64-linux-gnu/mesa/libGL.so
/usr/lib/x86_64-linux-gnu/mesa/libGL.so.1
/usr/lib/x86_64-linux-gnu/mesa/libGL.so.1.2.0
/usr/lib32/nvidia-331/libGL.so
/usr/lib32/nvidia-331/libGL.so.1
/usr/lib32/nvidia-331/libGL.so.331.38

There seemed to be two versions of the library file: one from MESA located in the standard library directory and another from NVIDIA located in its own directory. I guessed that the MESA file must be getting linked and at runtime it could not work with the NVIDIA display driver. A bit of Googling ended up in this bug report which painted a similar picture.

This bug was not yet fixed for my Ubuntu system. So, explicitly using the NVIDIA library file for linking, using -L/usr/lib/nvidia-331 acted as a workaround for this error. The program compiled and executed without any errors.

Tried with: NVIDIA drivers 331, Ubuntu 14.04 and NVIDIA GeForce 9600 GT