The 2024 Wheel Reinvention Jam just concluded. See the results.

About GetProcAddress and linking

So, I was rewatching a couple handmade heroes episodes, and a something that I would like to understand more popped up when a viewer asked a question about linking to opengl32.lib.

Here's the video I'm talking about: https://www.youtube.com/watch?v=5Klc9RZPG7M
The question is 1h08m into the video.

Casey explains to him that the only reason he calls GetProcAddress is because he would like to know if it fails.

This made me think, does it mean that I could just provide the function signature/prototype for a function I know GetProcAddress will return true, and use it directly instead of calling GetProcAddress?
So, I tried doing that and it didn't work, it left me with tons of unresolved symbols even though I was linking to the same libraries as when I was calling wglGetProcAddress(). What is different here?

Why must I get the function pointers via wglGetProcAddress()?

Edited by Italo on Reason: Initial post
Yes, technically it could work. But only if opengl32.lib file would actually contain definitions about functions you want to use and opengl32.dll file would export these functions. On Windows OpenGL dll/lib file provides functions only up to version 1.1. So for functions like glClearColor you can do that. But for functions that are 1.2 and up you cannot (like glCompileShader). On Windows GPU vendor provides its own OpenGL dll which gets used by wglGetProcess to lookup functions you ask. And for these dll files you don't have .lib files. You could generate them, but there is no guarantee that these functions are exported from dll. And anyway they are probably internal symbols, not exported.

If you would try this on Linux, you would see that it works because on all the current distributions GL library provides symbols for latest GL versions.

There is a different reason why you should use wglGetProcAddress function for getting these symbols. Your system can have different GPUs installed from different vendors - Intel/AMD/Nvidia. Each of which have completely different OpenGL implementations. If you would declare one global glClearColor function, how it would know which GPU should it use? Internally this function would lookup what is current GL context and then jump to real OpenGL implementation. But if you would use wglGetProcAddress to get address of function, it can look up actual real address because it knows which one to return based on currently bound GL context. Then you would immediately jump top actual implementation. So this is a small performance optimization.

Few years ago I have seen that on Windows the AMD driver is actually patching at runtime calls to glClearColor and other functions from OpenGL32.dll to call directly real implementation of these functions in AMD driver. Not sure if this is happening also now.

Edited by Mārtiņš Možeiko on
Thanks for the reply, you seem very knowledgeable about this, so may I try to clear up some things?

So from what I got you're saying that opengl32.lib/dll only has the symbols/implementations of older functions like glClear/glClearColor, and some windows specific functions like wglGetProcAddress().

I'm assuming wglGetProcAddress() calls the installed driver appropriate for the current opengl context. Am I right so far? If so, how does it call the driver, is it another .dll or something in a lower level?

Edited by Italo on
Yes, that is exactly right.

For nvidia, the OpenGL code is in nvoglv64.dll file (it is in C:\Windows\System32\DriverStore\FileRepository\nv_dispi.inf_amd64_5601d21ccd639df9 folder for me).
wglGetProcAddress returns pointer with address to code from this dll file.

You can easily verify this in Visual Studio debugger. Just check the value of function pointer returned by wglGetProcAddress, it wil include name of dll file it points to. Here's an example screenshot:

Edited by Mārtiņš Možeiko on
I understand it more now, thank you for the help.