Skip to content

GL \ Procedures query

Luca Piccioni edited this page Mar 9, 2017 · 6 revisions

Procedures query

Every OpenGL developer will face the problem of loading driver functions pointers to appropriately access to the extension system offered by the OpenGL API.

This issue is usually solved by linking a wrapper library, like the famous GLEW, but unfortunately this would work if you use an "un-managed" language like C or C++. Since OpenGL.Net is written in a managed language, it must manage the function pointers all the same, also for functions exported by the base operating system library (i.e. opengl32.dll on Windows platform).

OpenGL.Net automatically manages function pointers loading, almost like GLEW does (but with some significant differences). Indeed you can execute the functions without worrying about.

Function aliasing

This is a very important topic, since the application correctness may be affected by the knowledge of the issues deriving from the OpenGL function aliasing, and how they are managed within OpenGL.Net.

Introduction

What is a function alias?

A function alias is an OpenGL API function which is equivalent to another OpenGL API function. They have the number of arguments of the same type, they have the same return type and they are semantically equivalent; indeed the only difference is the actual function name.

Why there are function aliases?

The Khronos consortium has introduced a collaborative extension definition system that allows OpenGL implementers to introduce their extensions, and publish a specification that allow developers to take advantages of it. This is good, since this method allows a competitive environment that promote the evolution of the standard. Normally, when an extension is registered, the function names and symbols names are standardized by starting with gl (or GL_) and ending with the vendor suffix (i.e. ATI, AMD or NV).

When a vendor-specific extension is requested by the majority of the OpenGL users, most of vendors defines a common extension specification based on the original vendor-specific extensions (possibly unchanged); the new extension promotes the required functions and symbol by renaming them using the above convention, but using the common suffix EXT.

Finally, the common extensions can be included in the OpenGL standard; this is performed by including the extension specification in the OpenGL specification, and removing any suffix from function and symbol names.

When a function or a symbol is promoted, often (not always!) happens that the semantic of the function (or of the symbol) remains unchanged, hence the function aliasing.

The implementation

Normally, an OpenGL developer chooses a minimum version required for running the application. In this way he can assume the presence of certain API functions. In the case it is necessary to support older OpenGL implementation, without giving up features that allow faster executions, it is possible to support specific extension; however, the OpenGL developer must use a coherent set of function defined by each extension, since they could be coupled to work together (it is not a good idea to mix ARB with EXT with vendor-specific functions).

To overcome this issue, usually the developer fix a "promotion level" to be used (i.e. ARB or EXT), and occasionally update the relative code when the minimum requirements changes.

However, OpenGL.Net does not declare a method for each entry point available. Instead, make use of the function aliasing to scale the execution of the implementation currently available. Indeed a method can actually point to one of the many (aliasing) functions. For example, consider the following code:

[AliasOf("glGenBuffersARB")]
[RequiredByFeature("GL_VERSION_1_5")]
[RequiredByFeature("GL_VERSION_ES_CM_1_0", Api = "gles1")]
[RequiredByFeature("GL_ES_VERSION_2_0", Api = "gles2")]
[RequiredByFeature("GL_ARB_vertex_buffer_object")]
public static void GenBuffers(UInt32[] buffers) { ... }

It means that glGenBuffers can be aliased by glGenBuffers (core API, including ES variants) or glGenBuffersARB (defined by the GL_ARB_vertex_buffer_object_extension). But, which is the function actually called if multiple entry points are available?

The OpenGL.Net procedure loader prefers the following entry points, in that order:

  • Core API functions (OpenGL API or OpenGL ES API)
  • ARB extension functions (ARB suffix)
  • EXT extension functions (EXT suffix)
  • Vendor-specific extension functions

Note that aliasing statements are not generated based solely of the function signature; the aliasing information is provided directly from the OpenGL specification, since the aliasing is not about syntax, but it is about semantic. However, functions not being syntactically equivalent cannot be aliases even if they are declared as such.

The consequences

Indeed, you are aware that you cannot bind your application to the old extension methods. Instead, you need to take into account that the library entry points can execute core API functions. Usually this is not a problem, since strange side-effects due function promotion are very limited.

Automatic error checking (debug only builds)

Every function is checked against errors automatically; in this way is is possible to spot any error as soon it is generated, facilitating the application debugging. However, this feature is available only on debug builds.

Undefined function pointer

In the the user executes a function currently undefined on the running system, the method will throw a NullReferenceException. However, if running with a debug build, an assertion is executed with a descriptive message.

Clone this wiki locally