Why use 'glad' library for opengl initialization? [duplicate] - c++

This question already has answers here:
When do I need to use an OpenGL function loader?
(3 answers)
Closed 3 years ago.
I am learning now OpenGL and writing some geometrical abstractions over it for personal usage. I want my code to be maximally portable and I want to have GL context initialized in caller code (by means of FLTK, wxWidgets, WinAPI or any else supported platform).
I am reading now this popular article: https://learnopengl.com/Getting-started/Creating-a-window
Authors suggest there to use GLAD library, because this library provides creation of GL context (which does not fit me) and also it is used for 'retrieving addresses of functions' (quote: "Since there are many different versions of OpenGL drivers, the location of most of its functions is not known at compile-time and needs to be queried at run-time.").
My question is the following:
Does compiler really cannot get addresses of Opengl functions from GL-related .obj files which I specify in Linker Settings of Visual Studio? Do I really need to use wglGetProcAddress routine to refer to OpenGL functions? Is it possible to use OpenGL functions like any other functions from linked headers and .obj files?

Authors suggest there to use GLAD library, because this library provides creation of GL context (which does not fit me)
No, GLAD does not create or manage GL contexts in any way, and the website https://learnopengl.com/Getting-started/Creating-a-window never claims otherwise. They use GLFW for context and window management.
Does compiler really cannot get addresses of Opengl functions from GL-related .obj files which I specify in Linker Settings of Visual Studio?
No.
First of all, you do not specify OpenGL-related .obj files for the linker, but on Windows, you might use opengl32.lib, which is the import library file for opengl32.dll which comes with every windows version since Windows 95.
However, this DLL does not contain the OpenGL implementation you are typically using, but it contains Microsoft's OpenGL 1.1 GDI software rasterizer. The actual OpenGL implementation on windows is provided by an Installable Client Driver (ICD) which comes with your graphics driver. For OpenGL 1.0 and 1.1 functions, opengl32.dll will act as a trampoline and will forward the calls to the actual ICD DLL.
If you want to call any OpenGL function beyond OpenGL 1.1 (and that one is from 1997), you have to use the OpenGL extension mechanism in every case, as opengl32.dll does not provide these entry points at all, and the compiler/linker will of course not find them.

Related

Why are OpenGL functions loaded at runtime instead of dynamically linked?

Users of OpenGL APIs typically use a library such as GLEW or glad to load OpenGL functions at runtime. Why is dynamic loading the preferred linking method?
Static linking is clearly not an option since programs using OpenGL are typically compiled by the author and distributed to users who have different OpenGL libraries for their particular graphics cards.
That leaves dynamic linking and dynamic loading. It seems like dynamic linking could work since we know the names of all the functions we'll want to access.
Is dynamic linking a viable option? If not, why? If so, why is dynamic loading preferred?
What you want is possible. You can make a loader that is a DLL/SO with a static interface, which will load function pointers from the implementation behind the scenes. It will pipe function calls to the implementation, based on which context is current. Indeed, this is essentially how modern Linux distros work.
This is also how WGL works on Windows... up though OpenGL version 1.1, at any rate.
The reason it is not "preferred" is because it requires effort. Someone has to create and maintain this intermediary library that sits between the application and the driver. Whenever a new extension comes out, the library has to be updated. Whenever a new version comes out, the library has to be updated. And then you have to make sure to link with the right version of this library.
That additional dependency worked out OK on Linux, because it was kept up to date. OpenGL32.dll on Windows however was not. WinNT adopted OpenGL for a while, but Microsoft had also gone off and createdpurchased their own graphics API for Win9x. So they never updated OpenGL32.dll for later OpenGL versions or new extensions. And if they were willing to be non-backwards compatible, I imagine they'd have ditched OpenGL32.dll entirely from their OS.
Since you need a runtime loader to work in Windows, it's easier to just make all platforms work using the same runtime loader (though obviously with a different function fetching the function pointers). And while you could create the kind of DLL you're talking about, it would just be one more OpenGL loading library, one more dependency you have to maintain. Without the centralization that Linux/MESA brings to the table, there's just no point in bothering.
I was thinking that an application could be dynamically linked directly to the driver itself without an intermediate library
You can do that. However, you would be linking to that particular driver's library with a static import library. This means that if you link against NVIDIA's implementation, your application will fail to run on AMD's implementation.
And you can't statically link to import libraries for both DLLs. The reason being that if one static import library cannot be loaded, your application terminates. So unless you have both AMD and NVIDIA's implementations on your machine, you would not be able to run on either one.
Also:
since even though the driver library can't be available at compile time, we still know the OpenGL function names
That assumes that their drivers directly export those names. That is hardly guaranteed.
After all, the WGL/GLX interface is to use wgl/glXGetProcAddress to get function pointers. If the interface between WGL/GLX and the driver is simply to pass the string to the driver's function, then the driver doesn't need to export any functions directly. It exposes its API through a single entrypoint, forcing runtime function pointer loading rather than allowing static linking.
My understanding is that OpenGL loading libraries LoadLibrary/dlopen from dll/dylib/so library files which are themselves graphics card drivers and those driver libraries have symbol tables with OpenGL functions. Which parts of that are wrong?
All parts of that are wrong. You link against the basic interface API (like WGL or GLX). The loading library uses that interface to load function pointers. How the interface API translates loading a function pointer into the driver DLL is a platform-specific issue. On Windows, wglGetProcAddress calls a function in the driver, passing the string name of the function and getting back the function pointer.
On Linux, GLX tends to manufacture functions internally, using late-binding techniques to load the actual driver function later. That is, you can call glXGetProcAddress with some bogus name, and it will return a function pointer shim that, when called, will load the function for the current context from the driver.
The OpenGL wiki gives some insight into the OpenGL function loading process. Not that using the GetProcAddress functions amounts to a form of dynamic linking done outside of the operating system itself. From Wikipedia:
In computing, a dynamic linker is the part of an operating system that loads and links the shared libraries needed by an executable when it is executed (at "run time"), by copying the content of libraries from persistent storage to RAM, and filling jump tables and relocating pointers.
Extensions for OpenGL come out all the time and can be either available or not depending on vendors and driver platforms. The OpenGL wiki states that on MacOSX:
GL functions on OSX have been weak linked since OSX 10.2; this means that you can call them directly and unimplemented extensions will resolve to NULL. Note that this means that you must parse the extension string to determine if a function is valid or not, or your program will crash.
So even if Apple maintains a library to dynamically link with, you still need to add a layer to check whether a given function is available or not depending on the supported OpenGL version and extensions.

Why is OpenGL designed in a way that the actual functions have to be loaded manually at runtime?

I just had a read through Loading OpenGL Functions and wondered why OpenGL is designed that way, instead of the easy way, providing a dynamic library and the according headers?
providing a dynamic library and the according headers?
Then you have a misunderstanding of how a "dynamic library" works.
Let's take Windows as an example. On Windows, if all you had was "a dynamic library and the according headers", you would still be unable to just load that DLL and use it. Even the use of __declspec(dllimport) declarations in the header is insufficient. You need one more thing: an import library. This is a .lib that effectively does the job of loading function pointers for you when you load that DLL.
In short, it's syntactic sugar: nice to have, but not essential. A lot like an OpenGL Loading Library.
On Linux, things are a bit different. SO files are more self contained; they basically store the equivalent of an import library within them. So there, you could in theory get by with "a dynamic library and the according headers".
Even so, it's still sugar; you can dynamically load them and fetch function pointers manually if you wish.
All of that sugar theoretically could be used with OpenGL. But let's think about the ramifications of that.
On Windows, the import library is statically linked to your application. Therefore, it must work; if it fails to find the DLL, or that DLL does not provide the functions it ought to, then your program cannot run. At all. That's what most of those "missing DLL" errors are about; some static import library trying to find a DLL that doesn't exist.
So... what if I want to write an application that uses OpenGL 3.3 as a minimum, but is able to use features from OpenGL 4.5 if they are present? I can't link to the OpenGL 4.5 import library, since it'll fail to load on amy 3.3 implementation. So I have to link to the import library for OpenGL 3.3. But then, how do I access the 4.5 functions? That's right: I have to load function pointers if they exist.
So most people are going to have to load some functions anyway. It's much cleaner to just load the whole thing. That way, you don't have to have versioned import libraries.
Also, by loading all OpenGL functions dynamically, you don't have to wait for your OS vendor to update their DLL before you can use the next set of OpenGL functions. The main DLL simply provides a connection to the IHV driver DLL (or Open source driver on Linux) that actually implements OpenGL.
Note that Microsoft's OpenGL32.dll still only provides OpenGL 1.1. So I'd say we've benefited from not waiting on them ;)
Also, we have "the easy way": use an OpenGL Loading Library.

OpenGL apps code portability between different OS

I've checked numerous posts and tutorial about using OpenGL and C++. There is one thing that still bothers me. In each tutorial you have some additional library like GLFW, GLU, GLUT, WIN32 and so on (mostly used for window creation). Although I was unable to find some tutorial using only OpenGL. The only clue is this answer syaing that you need to use some library for this.
Can someone explain how it really is? How it looks when I want to use code on different operating systems? Is application code written with OpenGL 100% portable?
You can't have a tutorial which uses only OpenGL just because it's an API which doesn't provide such functionality.
OpenGL is not meant to create a graphical context in an operating system and use it, it is meant only to work directly with the GPU through a set of defined functions.
So the main point is that what you are asking resides outside the purpose of OpenGL, which defines just a standard interface to graphical operations.
But many more or less complete libraries exist to handle this problem and you also quoted some, for example GLFW or SDL, which takes care of initializing the context and manage also additional issues (for example controls or sounds).
The product will be portable if a set of constraints is respected:
you are using a library which manages different OS for handling the graphical context (eg GLFW)
you are using an OpenGL profile which is supported by all the GPUs you mean to make your code work on
in case of portability between OpenGL and OpenGL ES you must ensure additional constraints since the latter managed certain things differently

Beginner to learning OpenGL - what are these OpenGL tools?

I would like to start learning OpenGL, to use it in software written in C++ language. The natural thing I do when attempting to learn something new is acquiring proper literature and online tutorials.
With OpenGL however, I got stuck. Different literature and tutorials that I have checked almost immediately mention terms, like :
Unofficial OpenGL SDK
GLSL
FreeGLUT
SFLW
GLEW
GLFW
others ...
Even though I checked the websites of these tools or wiki entries, I still don't understand things like : what are they actually with relation to OpenGL, why use one and not another, what do they have in common, what are the differences... And probably most importantly, how do I find what I ( don't ) need ?
So I would very much like to hear an explanation on this topic. Reference to a proper online reading is good as well. Thank you.
Open Graphics Library (OpenGL) is a cross-language, cross-platform application programming interface (API) for rendering 2D and 3D vector graphics. As such, it only provides means for drawing basic primitives (like points, lines, triangles), but no high-level functionality. Let's work through your list:
The "Unofficial OpenGL SDK"
This is just a collection of libraries offering some (more or less) often required functionality, like loading image files, or working with 3D objects, or helper libraries for creating and managing OpenGL contexts (it does include some of the other libraries you mention, we're coming to that.) I wouldn't recommend using that SDK as a beginner, but just learn the basics and carefully select the additional libraries you want to use.
OpenGL Shading Language (abbreviated: GLSL or GLslang), is a high-level shading language based on the syntax of the C programming language.
This is not a separate tool, but a central concept of modern OpenGL. You will need it to write your shaders (which are required in modern GL). That's something you definitively have to learn, but the compiler for this language comes with your GL implementation, so this is nothing you have to install separately.
FreeGLUT, GLFW, SFLM
As I already said, OpenGL is defined platform-independent. One still needs a platform-specific API to actually create the OpenGL contexts and "connect" them to the windows (or whatever "drawables" there are on the platform). OpenGL does not even have a concept of a "window", and as such, also no means for input event handling, detecting window resizes. These libraries implement wrappers for those platform-specific GL binding APIs and the window and event management, so you can just create a OpenGL context and a suitable window without having to care about all those platform-specific details. FreeGLUT and GLFW are quite focused on providing a simple framework for OpenGL development, while SFML is a more generic multimedia framework (also supporting things like audio output) and is capable of creating OpenGL contexts and windows. Other such libraries would be SDL (which is often used for games), or Qt which supports OpenGL widgets.
GLEW is short for "OpenGL extension wrangler".
This is a OpenGL loading library. OpenGL is an extensible
API. As such, features might or might not be present on the machine your application is executed. Furthermore, the way the OpenGL is defined on some platforms, only a certain set of functions is guaranteed to be exported by the libraries. If you need features of newer versions, you have to use the extension mechanism. This means that, instead of directly linking a function at link time, you have to query the function pointers at runtime to get access to those functions. To simplify that process, such loader libraries as GLEW do exist. With GLEW, all you need to do is call glewInit() and then you can use any GL function as you like (as long as it is supported by the implementation), forgetting about all those details of the extension mechanism.
What you really "need" of this list: GLSL, but that's not a tool. The other stuff is for convenience, but I highly recommend using some platform-independent window and context management library (GLFW is quite lightweight, but it is hard to tell what you will need. For learning OpenGL, GLFW is surely a good choice.) and also some GL loader like GLEW.

Getting OpenGL API functions

I'm looking at the OpenGL wiki page, and I was curious about the following line:
For reasons that are ultimately irrelevant to this discussion, you must
manually load functions via a platform-specific API call. This boilerplate
work is done with various OpenGL loading libraries; these make this process
smooth. You are strongly advised to use one. —OpenGL Wiki
Intuitively, you would think they would just provide a header for you to include. So, what are the historic reasons for this?
EDIT :
Thanks for the answers, I see now that that OpenGL supports multiple implementations of its functions, so there is no one single DLL/SO that everyone links to. I also found these quotes helpful:
The OpenGL library supports multiple implementations of its functions. From MSDN
To accommodate this variety, we specify ideal behavior instead of actual behavior for certain GL operations. From GL Spec
When you run your program, opengl32.dll gets loaded and it checks in the Windows registry if there is a true GL driver. If there is, it will load it. For example, ATI's GL driver name starts with atioglxx.dll and NVIDIA's GL driver is nvoglv32.dll. The actual names change from release versions GL FAQ
I also found that Intel doesn't provide up-to-date implementation for OpenGL, so even though I have an i7-2500, I only have OpenGL 3.0 :(.
It has nothing to do with history. That's just how it is.
OpenGL implementations, by and large, come from some form of shared library (DLL/SO). However, this is complicated by the fact that you don't own the OpenGL "library"; it's part of the system infrastructure of whatever platform your code is running on. So you don't even know what specific DLL you might be using on someone else's computer.
Therefore, in order to get OpenGL function pointers, you must use the existing infrastructure to load them.
One of the main reasons is extensions: On every platform, OpenGL has always supported platform-specific extensions. These couldn't be part of the official headers, as they were usually added by the vendors in-between spec updates. In addition, those vendor-specific extensions may live in completely weird DLL/SO, for instance, deep inside the driver. There is also no guarantee that the driver DLL exports them under their "canonical" name, so OpenGL relied very early on platform-specific stuff to load a function pointer. This makes the whole extension thing feasible.
On all platforms, you usually do get some OpenGL without using extensions (OpenGL 1.4 or so), but as the extension method was successful and is easy to implement, everyone uses it now (similar for OpenCL!)
On the Mac, you don't need to load function pointers, you just include a header and link against the OpenGL framework.