How to test if OpenGL application works against some particular OpenGL version?

Viewed 220

Recently I realized my application is using an OpenGL call which is available only on OpenGL 4.5 - glCreateTextures, and I realized it only because I was trying to run the application on a MacOS computer supporting only OpenGL 4.1 and it crashed there.

The application requests OpenGL 4.0 core profile, 3.2 core profile and 3.2 forward compatible core profile (in this order), but in spite of obtaining a 4.0 profile a call to glCreateTextures succeeds without any warning.

I would like my application to run on anything supporting 3.2, but I do not have a regular access to hardware which does not actually support 4.5. There might be other issues like this both in API and shader use lurking around which prevent compatibility with lower OpenGL versions and I would like to know about them.

How can I test my application to make sure it works with some particular version of OpenGL (3.2, 4.0) without actually running it on a hardware which does supports newer version?

In my case the application is running on JVM (written in Scala or Java) and uses LWJGL + GLFW bindings, but even knowing how do this for native C/C++ applications would be helpful, if there is a way, it should be probably possible to transform it into the JVM world.

1 Answers

This is a general problem with OpenGL and there not being a difference between loading a core function and an equally-named extension function.

In the case of glCreateTextures, this OpenGL function both comes from the ARB_direct_state_access extension as well as from OpenGL 4.5 (where that function became core) with equal name.

What actually happens in the concrete context of LWJGL is that it will check at runtime whether the context supports OpenGL 4.5 (there is a definitively function for that since OpenGL 3.0 which allows to check whether an OpenGL context supports a particular core version). And LWJGL will find that this check returns false when you request a core profile e.g. 3.3 core.

However, LWJGL also checks the existence of every advertized OpenGL extension and loads the function pointers of all exposed functions from those extensions. And in your case, when you request e.g. a 3.3 core context, but your driver still exposing ARB_direct_state_access (which is perfectly fine) then LWJGL will load the function pointer for glCreateTextures just fine. And since there is no difference in routing GL function calls in LWJGL when you call it through a core GL class or through an extension class (it's still the same underlying GL function after all), the call will succeed.

Now to solve this problem, there is a GitHub issue to allow an LWJGL client to exclude certain extensions from being loaded: https://github.com/LWJGL/lwjgl3/issues/683

Once this has landed in an LWJGL 3 release, functions that are not core in your requested GL core version will not be visible/available when you also exclude the extension.

Another way to at least reduce the risk of using a GL function that comes from a higher GL version than the one your app is targeting, is to simply not use any methods from a org.lwjgl.opengl.GLxyC class where x.y is higher than the GL version your app is targeting.

So in effect, when you say:

Recently I realized my application is using an OpenGL call which is available only on OpenGL 4.5 - glCreateTextures, and I realized it only because I was trying to run the application on a MacOS computer supporting only OpenGL 4.1 and it crashed there.

then one can argue that this is on you. Because it means that you were deliberately using an OpenGL function from a GL45 class, so you wanted to target OpenGL 4.5.

Related