June 19, 2016

DerelictOGL: DerelictGL3 Reborn?

I’m currently experimenting with a new approach to loading OpenGL in Derelict. What I’ve done is to put all of the declarations into manifest constant strings according to GL version and set things up so that a loading function for each is automatically registered when the string is mixed in. So then you can do this:

import derelict.ogl;

// This is the new thing here
mixin(DerelictGL33);

void main()
{
    // Load the shared library + OpenGL 1.1
    DerelictOGL.load();

    // Create an OpenGL context
    ...

    DerelictOGL.reload();
}

So the approach for loading the shared library and then the extended versions and extensions is the same. Aside from the name changes, the only difference is the mixin at the top of the file. The idea is that you would create your own OpenGL module (e.g. mygl), publicly import derelict.ogl, then mixin the version you want along with any extensions you intend to use.

One goal is to reduce the binary size by getting rid of the cruft you don’t want to use. Another is to make it possible to actually mix the function pointers in to a context object rather than having them as globals. Whether or not this proves practical remains to be seen.

At the moment, I’ve hit a brick wall with OpenGL 3.0+. Given that some of the ARB extensions were promoted to core with the same function and type names (names that had no ARB suffix even in the extension specification) For example, the declarations in GL_ARB_framebuffer_object are the same in the extension as they are in OGL 3.0. I haven’t yet figured a way to implement the mixins such that the user can mixin both the extension and the 3.0 functions without a conflict.

I have no idea if this is going to prove feasible in the long run. If it does, this will almost certainly become a new package rather than DerelictGL3 2.0. If it doesn’t, well, it was an interesting diversion.

June 06, 2016

Loading Conditionally Compiled GLFW 3 Functions

Only a few days after the release of DerelictGLFW3 3.0, I’ve tagged a 3.1 release. Four functions that were loaded automatically no longer are and a new public function was added to the DerelictGLFW3 loader, hence the version bump. The reason for the change is because of a new feature that no other Derelict binding currently has.

Throughout the binding’s existence, I have largely ignored the conditionally compiled native functions in the GLFW API. I added two Windows-specific and two Mac-specific functions to the binding as part of a pull request some time ago. This was fine, as, even though they were conditionally compiled, they were always present on the given platforms. I was also able to implement the return values in a way that didn’t require any platform-specific type declarations that might conflict with, say, custom bindings to the Cocoa API on Mac.

More native functions were added in GLFW 3.1 and, in GLFW 3.2, functions that depend on the Vulkan API were added. I thought I could get away without implementing them initially and put it off to later, but a couple of days after I announced the new version, an issue was reported on github wiht a possible solution (using a subclass of DerelictGLFW3Loader specifically for Vulkan functions). In my previous post, I already had a solution in mind using string mixins. In the end, I implemented using template mixins instead and, after it was tested, tagged the 3.1 release.

The problem is that the functions are declared using types specific to external APIs, such as the Vulkan API, or the Win32 API. I would either have to use C-style generic types (void*) where possible or declare my own types in Derelict. That, as has been shown in the past, will only lead to conflicts when a user imports types declared in a different binding that and try to use the functions from DerelictGLFW3.

Moreover, while I can be guaranteed that the Windows- and Mac-specific functions will be present on (almost) any GLFW binaries on those platforms, the same cannot be said of EGL, Vulkan, Mir, Wayland, or even X11. Adding these directly to the loader by default will result in exceptions when they are not present, forcing nearly every GLFW user to work around that with the selective loading mechanism. Quite far from an ideal situation.

By using template mixins, client code can import any binding with the types they need and then use the relvant GLFW functions without fail. For example:

import core.sys.windows.windows : HWND, HGLRC;
import derelict.glfw3;

mixin DerelictGLFW3_WindowsBind;

With this, the three Windows-specific functions declared in glfw3native.h will be available in client code. When compiling DerelictGLFW3 as a static binding, that’s all that need be done. For the default dynamic binding, the functions still need to be loaded.

void main() {
    DerelictGLFW3.load();
    DerelictGLFW3_loadWindows();
}

The loaders load method must be called first, then the free fucniton that loads the mixed in functions can be called.

Obviously, core.sys.windows.windows is part of DRuntime and I could depend on that in Derelict without resorting to mixins, but for consistency the Windows stuff uses the same approach as the other conditionally compiled functions where I don’t have that luxury. You can read more about which mixins and loaders all available, including which ones alias to DerelictGLFW3_NativeBind and DerelictGLFW3_loadNative, in the DerelictGLFW3 documentation.

Note that the system-specific stuff in DerelictGL3 has the same potential problem with type conflicts. However, since I moved the to using the DRuntime Win32 bindings, that potential has dramatically decreased (seems no one really uses any of the platform-specific stuff there anyway). I will most likely apply this technique there anyway to help shrink the size of the bindings a bit. I also intend to explore using it with the OpenGL extensions.

But that’s for another day and another post. Now it’s back to bothering people via email in my pursuit of content for the new D Blog.