Jump to page: 1 2 3
Thread overview
glad OpenGL loader generator
Aug 05, 2013
David
Aug 05, 2013
w0rp
Aug 05, 2013
Justin Whear
Aug 05, 2013
David
Aug 05, 2013
Justin Whear
Aug 05, 2013
David
Aug 10, 2013
Andrej Mitrovic
Aug 05, 2013
Land
Aug 06, 2013
David
Aug 10, 2013
Russel Winder
Aug 06, 2013
David
Aug 06, 2013
David
Aug 07, 2013
Mike Parker
Aug 12, 2013
evilrat
Aug 12, 2013
David
Aug 13, 2013
evilrat
Aug 13, 2013
David
Aug 13, 2013
evilrat
Aug 14, 2013
Brad Anderson
Aug 13, 2013
David
Aug 25, 2013
David
August 05, 2013
glad - is an OpenGL loader (with experimental gles support, --api=gles2) which is generated 1:1 from the OpenGL official spec (https://cvs.khronos.org/svn/repos/ogl/trunk/doc/registry/public/api/gl.xml). It has at the moment a "backend" for three languages (frontend parses, backend generates code, like constants and function pointers).

https://github.com/Dav1dde/glad

What are the advantages over e.g. Derelict?

* supports *every* opengl extension
* always up to date
* (basically) never incorrect bindings
* easy to maintain
* easy API, 3 functions
* allows you to use your own loader

And the more important:
* provides an easy way to check if extension X is loaded
`enforce(GL_EXT_Cg_shader)` (same works for OpenGL versions
`enforce(GL_VERSION_3_2)`)
* glad generates loaders exactly for your needs. If you only need a
OpenGL 3.2 core profile with two extensions, glad can generate exactly
this code. Making your binding small, without overhead.


What your code might look like with glad:

import glad.gl; // imports all constants and functions, including extensions
import glad.loader : gladInit, gladTerminate, gladLoadGL;
void main() {
    gladInit();
    scope(exit) gladTerminate();

    /* setup OpenGL context with e.g. glfw */

    auto glv = gladLoadGL();
    enforce(glv.major == 3 && glv.minor == 2);
    // or: enforce(GL_VERSION_3_2);
    enforce(GL_EXT_texture_filter_anisotropic);

    /* done, use OpenGL here */
}

gladInit() and gladTerminate() are not needed if you provide your own
loader, e.g. you use SDL:

void main() {
    /* setup OpenGL context with SDL */

    auto glv = gladLoadGL(&SDL_GL_GetProcAddress);
    enforce(glv.major == 3 && glv.minor == 2);

    /* done, use OpenGL here */
}

A fully blown OpenGL 4.4 compatability, all extensions loader:
https://github.com/Dav1dde/glad/tree/d
But I really recommend generating your own loader/binding for your exact
needs!

python main.py --generator=d --extensions=GL_EXT_texture_filter_anisotropic --out-path=build


A example in C: https://github.com/Dav1dde/glad/blob/master/example/c/simple.c (to show glad is not rocket science!)



------- Slightly Offtopic, why Derelict/Dynamic linking is bad  --------

glad was mainly written to have an easy backend to support multiple languages at a time, but also to get rid of Derelict as a dependency.

(warn: dynamic/static linking "rant")

OpenGL was the only reason I still used Derelict, now I could get rid of
another relativly big dependency. Don't get me wrong Derelict is great,
but dynamic loading isn't! Unfortunatly you have to dynamically load OpenGL.

Why is dynamic loading a problem?
Well static linking has several important advantages:
* slightly faster startup times
* easier to distribute
* no DLL hell like on windows! with all it's DLLs, it's a mess!
https://en.wikipedia.org/wiki/DLL_hell

If you depend on a system-wide installation of a library you get another problem Windows might have a different DLL than Ubuntu a .so  or Archlinux or Debian old stable, so you have to ship your DLLs with you or depend on a specific version, which makes distribution a lot harder.

You might say, but on Windows, I can't statically link because dmc doesn't really work (e.g. Makefiles not supporting DM Make), objconv (another dependency next to the C compiler) etc... Well on Windows you can still use an import library. Which brings us to the next advantage. You don't need two separate librarys for one and the same binding (one which works like a C-Header and one with a ton of function pointers and loader code attached).

August 05, 2013
I'm glad you invested time in glad. I'll probably try it out soon enough.
August 05, 2013
It looks like your D backend generates string literals with literal null bytes--this is unnecessary as string literals are already null terminated. (Documented here: http://dlang.org/interfaceToC.html (see final bullet under "Call­ing C Func­tions")

Also, it looks like loading each extension requires scanning all available extension names, e.g. loading 25 extensions requires 25 linear scans of the extension list.  You might consider caching and sorting if the number of extensions requested is more than a handful.
August 05, 2013
Am 06.08.2013 00:17, schrieb Justin Whear:
> It looks like your D backend generates string literals with literal null bytes--this is unnecessary as string literals are already null terminated. (Documented here: http://dlang.org/interfaceToC.html (see final bullet under "Call­ing C Func­tions")

This is (was) on purpose.
I should probably change that now, since it will confuse people. I had
for a short time a mess in the generators and tried to use the D
generator to build for another language too, which required the explicit
\0 and .ptr

> Also, it looks like loading each extension requires scanning all available extension names, e.g. loading 25 extensions requires 25 linear scans of the extension list.  You might consider caching and sorting if the number of extensions requested is more than a handful.

I was thinking of that, too, but caching the OpenGL call to glGetStringi, I don't think you can prevent the linear searches.

August 05, 2013
On Tue, 06 Aug 2013 00:21:46 +0200, David wrote:
> I was thinking of that, too, but caching the OpenGL call to glGetStringi, I don't think you can prevent the linear searches.

Why not something like this for the GL_VERSION >= 3 codepath in has_ext?
-----------------------------------
static auto availableExts;

if (availableExts.empty)
{
    int num;
    glGetIntegerv(GL_NUM_EXTENSIONS, &num);
    availableExts = new string[](num);

    foreach (i, ref extName; availableExts)
	extName = (cast(const(char)*)glGetStringi(GL_EXTENSIONS, i)).idup;

    availableExts.sort();
}

// Use binary search
return assumeSorted(availableExts).contains(ext);
-----------------------------------
August 05, 2013
I really like the sound of this. I'll try it out tomorrow.
August 05, 2013
Am 06.08.2013 00:33, schrieb Justin Whear:
> On Tue, 06 Aug 2013 00:21:46 +0200, David wrote:
>> I was thinking of that, too, but caching the OpenGL call to glGetStringi, I don't think you can prevent the linear searches.
> 
> Why not something like this for the GL_VERSION >= 3 codepath in has_ext?
> -----------------------------------
> static auto availableExts;
> 
> if (availableExts.empty)
> {
>     int num;
>     glGetIntegerv(GL_NUM_EXTENSIONS, &num);
>     availableExts = new string[](num);
> 
>     foreach (i, ref extName; availableExts)
> 	extName = (cast(const(char)*)glGetStringi(GL_EXTENSIONS, i)).idup;
> 
>     availableExts.sort();
> }
> 
> // Use binary search
> return assumeSorted(availableExts).contains(ext);
> -----------------------------------
> 

Thanks, I will definitly look into improving it (when I wake up ;))
August 06, 2013
Am 06.08.2013 01:11, schrieb Land:
> I really like the sound of this. I'll try it out tomorrow.

glad to hear that ;) (to join w0rp with glad jokes)
August 06, 2013
I posted it also on reddit, maybe it draws some attention: http://www.reddit.com/r/programming/comments/1jt9m5/multilanguage_opengl_loader_generator_based_on/
August 06, 2013
Am 06.08.2013 16:32, schrieb David:
> I posted it also on reddit, maybe it draws some attention: http://www.reddit.com/r/programming/comments/1jt9m5/multilanguage_opengl_loader_generator_based_on/
> 
Interesting it seems like it was deleted, but I don't know why? ... Ok
« First   ‹ Prev
1 2 3