-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
Fixed OpenGL entry point loading on Windows #2478
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Codecov Report
Additional details and impacted files@@ Coverage Diff @@
## master #2478 +/- ##
==========================================
+ Coverage 25.83% 25.84% +0.01%
==========================================
Files 226 226
Lines 19420 19420
Branches 4715 4712 -3
==========================================
+ Hits 5017 5020 +3
+ Misses 13869 13866 -3
Partials 534 534
Continue to review full report in Codecov by Sentry.
|
bc4587b
to
405e8e7
Compare
405e8e7
to
af23322
Compare
Updated. |
af23322
to
ee3ac1c
Compare
Rebased to master. |
69e9222
to
b4f6648
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not confident on the OpenGL-related logic here but I am happy with the code changes.
…ailing to load if they are not provided by the vendor provided library on Windows.
b4f6648
to
1517d6c
Compare
This is causing crashes. |
The way OpenGL entry points are loaded on Windows is unique compared to other platforms. Whereas on other platforms, the entry points returned by e.g.
glXGetProcAddressARB
can be used independently of the context they were queried in, the entry points returned bywglGetProcAddress
should only be used in the context they were queried in. This means in theory, any OpenGL function could have multiple different addresses on Windows depending on the context that was active when the query was made.In practice, we just have to differentiate between 2 cases on Windows, either an ICD (hardware accelerated vendor driver) is available or an ICD is not available. In the former case,
wglGetProcAddress
forwards the query to the ICD providing the context that is currently active and it returns the address of the function from the concrete ICD .dll. In the latter case, when an ICD is not available, Windows provides a generic GDI software rendering implementation. For whatever reason, when the generic implementation is in use,wglGetProcAddress
cannot be used to query entry points available for the active context, it will always returnNULL
. Instead they have to be loaded from the generic implementation library (OpenGL32.dll) itself usingGetProcAddress
.So in summary:
wglGetProcAddress
GetProcAddress
The current implementation in SFML isn't 100% correct since it will try to fall back to
GetProcAddress
even when an ICD context is active butwglGetProcAddress
does not return an address for whatever reason.This is bad for 2 reasons:
This change fixes OpenGL entry points being loaded from OpenGL32.dll instead of failing to load if they are not provided by the ICD on Windows.
This is technically still not a 100% correct implementation, since in theory there could be multiple ICDs installed on a given system, each providing their specific entry points. The entry points would have to be stored per context that is created instead of globally for the entire application. Because this scenario occurs so rarely if at all, any OpenGL entry point loader (like glad which SFML uses) assumes the same entry points can be used across any context that is created by the application and thus stores them globally. This is correct on any platform except Windows, but I guess they weren't willing to make an exception just for Windows.
The only way to test this is by running a test application on both a system that has an ICD installed and one that only provides the generic implementation and inspecting where the function pointers originate from. In the former case, they should be addresses in the ICD (e.g. atioglxx.dll for AMD, nvoglv32.dll for Nvidia) and in the latter case they should be addresses inside OpenGL32.dll.