Questions about Desktop OpenGL loaders #4390

Closed
opened 2021-08-03 08:40:42 +00:00 by NancyLi1013 · 7 comments
NancyLi1013 commented 2021-08-03 08:40:42 +00:00 (Migrated from github.com)

Version/Branch of Dear ImGui:

Version: 1.83
Branch: master

Back-end/Renderer/Compiler/OS

Back-ends: imgui_impl_opengl3.cpp
Compiler: GCC 11.1.0
Operating System: Ubuntu 18.04

My Issue/Question:

When using imgui in vcpkg, we found that imgui failed to compile with the following errors(Please see the details in Screenshots/Video part). Through investigation, we noticed that it seems like there is only one OpenGL loader supported for once in imgui_impl_opengl3.h.
ocornut/imgui@f99fe72c42/backends/imgui_impl_opengl3.h (L48-)#L83

Could you please help confirm if these OpenGL loaders are mutually exclusive each other?

Thanks in advance.

Screenshots/Video

[build] : && /bin/x86_64-linux-gnu-g++-11 -g  CMakeFiles/hello.dir/main.cpp.o -o hello  /home/dylan/repositories/github/Microsoft/vcpkg/installed/x64-linux/debug/lib/libimguid.a  /home/dylan/repositories/github/Microsoft/vcpkg/installed/x64-linux/debug/lib/libglad.a  /home/dylan/repositories/github/Microsoft/vcpkg/installed/x64-linux/debug/lib/libglfw3.a  /usr/lib/x86_64-linux-gnu/librt.so  -lm  -ldl  /usr/lib/x86_64-linux-gnu/libX11.so  -lpthread && :
[build] /usr/bin/ld: /home/dylan/repositories/github/Microsoft/vcpkg/installed/x64-linux/debug/lib/libimguid.a(imgui_impl_opengl3.cpp.o): in function `ImGui_ImplOpenGL3_Init(char const*)':
[build] /home/dylan/repositories/github/Microsoft/vcpkg/buildtrees/imgui/src/v1.83-af20d68e6e.clean/backends/imgui_impl_opengl3.cpp:163: undefined reference to `glGetIntegerv'
[build] /usr/bin/ld: /home/dylan/repositories/github/Microsoft/vcpkg/buildtrees/imgui/src/v1.83-af20d68e6e.clean/backends/imgui_impl_opengl3.cpp:164: undefined reference to `glGetIntegerv'
[build] /usr/bin/ld: /home/dylan/repositories/github/Microsoft/vcpkg/buildtrees/imgui/src/v1.83-af20d68e6e.clean/backends/imgui_impl_opengl3.cpp:168: undefined reference to `glGetString'
[build] /usr/bin/ld: /home/dylan/repositories/github/Microsoft/vcpkg/buildtrees/imgui/src/v1.83-af20d68e6e.clean/backends/imgui_impl_opengl3.cpp:232: undefined reference to `glGetIntegerv'
[build] /usr/bin/ld: /home/dylan/repositories/github/Microsoft/vcpkg/installed/x64-linux/debug/lib/libimguid.a(imgui_impl_opengl3.cpp.o): in function `ImGui_ImplOpenGL3_SetupRenderState(ImDrawData*, int, int, unsigned int)':
[build] /home/dylan/repositories/github/Microsoft/vcpkg/buildtrees/imgui/src/v1.83-af20d68e6e.clean/backends/imgui_impl_opengl3.cpp:251: undefined reference to `glEnable'
[build] /usr/bin/ld: /home/dylan/repositories/github/Microsoft/vcpkg/buildtrees/imgui/src/v1.83-af20d68e6e.clean/backends/imgui_impl_opengl3.cpp:252: undefined reference to `__glewBlendEquation'
[build] /usr/bin/ld: /home/dylan/repositories/github/Microsoft/vcpkg/buildtrees/imgui/src/v1.83-af20d68e6e.clean/backends/imgui_impl_opengl3.cpp:253: undefined reference to `__glewBlendFuncSeparate'

Standalone, minimal, complete and verifiable example: (see https://github.com/ocornut/imgui/issues/2261)

// Here's some code anyone can copy and paste to reproduce your issue
main.cpp:

#include <glad/glad.h>
#include <imgui_impl_opengl3.h>

int main()
{
  ImGui_ImplOpenGL3_Init();
}

CMakeLists.txt:

cmake_minimum_required(VERSION 3.18)
project(hello)

find_package(glad CONFIG REQUIRED)
find_package(imgui CONFIG REQUIRED)

add_executable(hello main.cpp)
target_link_libraries(hello PRIVATE glad::glad imgui::imgui)
**Version/Branch of Dear ImGui:** Version: 1.83 Branch: master **Back-end/Renderer/Compiler/OS** Back-ends: imgui_impl_opengl3.cpp Compiler: GCC 11.1.0 Operating System: Ubuntu 18.04 **My Issue/Question:** When using `imgui `in vcpkg, we found that `imgui `failed to compile with the following errors(Please see the details in Screenshots/Video part). Through investigation, we noticed that it seems like there is only one OpenGL loader supported for once in imgui_impl_opengl3.h. https://github.com/ocornut/imgui/blob/f99fe72c42bd5d578c2443409192b139b1c6623d/backends/imgui_impl_opengl3.h#L48-#L83 Could you please help confirm if these OpenGL loaders are mutually exclusive each other? Thanks in advance. **Screenshots/Video** ``` [build] : && /bin/x86_64-linux-gnu-g++-11 -g CMakeFiles/hello.dir/main.cpp.o -o hello /home/dylan/repositories/github/Microsoft/vcpkg/installed/x64-linux/debug/lib/libimguid.a /home/dylan/repositories/github/Microsoft/vcpkg/installed/x64-linux/debug/lib/libglad.a /home/dylan/repositories/github/Microsoft/vcpkg/installed/x64-linux/debug/lib/libglfw3.a /usr/lib/x86_64-linux-gnu/librt.so -lm -ldl /usr/lib/x86_64-linux-gnu/libX11.so -lpthread && : [build] /usr/bin/ld: /home/dylan/repositories/github/Microsoft/vcpkg/installed/x64-linux/debug/lib/libimguid.a(imgui_impl_opengl3.cpp.o): in function `ImGui_ImplOpenGL3_Init(char const*)': [build] /home/dylan/repositories/github/Microsoft/vcpkg/buildtrees/imgui/src/v1.83-af20d68e6e.clean/backends/imgui_impl_opengl3.cpp:163: undefined reference to `glGetIntegerv' [build] /usr/bin/ld: /home/dylan/repositories/github/Microsoft/vcpkg/buildtrees/imgui/src/v1.83-af20d68e6e.clean/backends/imgui_impl_opengl3.cpp:164: undefined reference to `glGetIntegerv' [build] /usr/bin/ld: /home/dylan/repositories/github/Microsoft/vcpkg/buildtrees/imgui/src/v1.83-af20d68e6e.clean/backends/imgui_impl_opengl3.cpp:168: undefined reference to `glGetString' [build] /usr/bin/ld: /home/dylan/repositories/github/Microsoft/vcpkg/buildtrees/imgui/src/v1.83-af20d68e6e.clean/backends/imgui_impl_opengl3.cpp:232: undefined reference to `glGetIntegerv' [build] /usr/bin/ld: /home/dylan/repositories/github/Microsoft/vcpkg/installed/x64-linux/debug/lib/libimguid.a(imgui_impl_opengl3.cpp.o): in function `ImGui_ImplOpenGL3_SetupRenderState(ImDrawData*, int, int, unsigned int)': [build] /home/dylan/repositories/github/Microsoft/vcpkg/buildtrees/imgui/src/v1.83-af20d68e6e.clean/backends/imgui_impl_opengl3.cpp:251: undefined reference to `glEnable' [build] /usr/bin/ld: /home/dylan/repositories/github/Microsoft/vcpkg/buildtrees/imgui/src/v1.83-af20d68e6e.clean/backends/imgui_impl_opengl3.cpp:252: undefined reference to `__glewBlendEquation' [build] /usr/bin/ld: /home/dylan/repositories/github/Microsoft/vcpkg/buildtrees/imgui/src/v1.83-af20d68e6e.clean/backends/imgui_impl_opengl3.cpp:253: undefined reference to `__glewBlendFuncSeparate' ``` **Standalone, minimal, complete and verifiable example:** _(see https://github.com/ocornut/imgui/issues/2261)_ ``` // Here's some code anyone can copy and paste to reproduce your issue main.cpp: #include <glad/glad.h> #include <imgui_impl_opengl3.h> int main() { ImGui_ImplOpenGL3_Init(); } CMakeLists.txt: cmake_minimum_required(VERSION 3.18) project(hello) find_package(glad CONFIG REQUIRED) find_package(imgui CONFIG REQUIRED) add_executable(hello main.cpp) target_link_libraries(hello PRIVATE glad::glad imgui::imgui) ```
NancyLi1013 commented 2021-08-03 08:41:36 +00:00 (Migrated from github.com)
Related issue in vcpkg: https://github.com/microsoft/vcpkg/issues/19231 https://github.com/microsoft/vcpkg/issues/14753
ocornut commented 2021-08-03 09:05:06 +00:00 (Migrated from github.com)

OpenGL loaders are a terrible mess but somehow in 13 years since GL3 nothing has been standardized leaving it to third party loaders to retrieve the function pointers. This makes sharing/reusing OpenGL code accross projects immensely painful.

The loaders essentially provide two things: variety of defines/enum, and function pointers named after OpenGL functions. Those functions pointers are NULL during startup, and “initializing” a loader essentially sets them at runtime.

The main confusion - what many people misunderstand - it that what matter is which loader the imgui_impl_opengl3.cpp COMPILATION UNIT sees.
And because we don’t attempt to initialize the loader ourselves, the user application needs to initialize the same loader on their side too (*).

What your snippets omit is telling the opengl3.cpp backend which loader to use. There is a define for that. It’s not possible to make a runtime option because in a same compilation unit, two loaders would conflicts since their headers provide defines and function pointers. In a same project it is technically possible to have multiple loaders (not particularly useful but i imagine in megaapps with many librairies it’s probable that it happens). Conservely there is not added value to using user’s loader or any specific loader. We just somehow need those opengl defines and function pointers, regardless of where they come from (**)

Adding to the confusion the fact that is that define is omitted, we attempt to detect a loader based on available include paths. In retrospect maybe this wasn’t a good idea as it can make things confusing for users. You can’t rely on autodetection if your include paths contains other loaders.

From vcpkg point of view, each loader should be its own library and the user should still be responsible for initializing it. Its annoying.

(*) Last time I checked none of the loader had issue initializing more than once, so I was thinking maybe if imgui_impl_opengl3 did also try to initlaize the loader it sees, it would decrease number of issues (but essentially it’ll make cases where user think they are using loader A but backend actually see loader B “silently work” instead of “fail”. That’s quite debatable)

(**) Another solution may be to bite the bullet and develop/embed our own loader OR find a loader we can embed into the backend and get done with it…..

OpenGL loaders are a terrible mess but somehow in 13 years since GL3 nothing has been standardized leaving it to third party loaders to retrieve the function pointers. This makes sharing/reusing OpenGL code accross projects immensely painful. The loaders essentially provide two things: variety of defines/enum, and function pointers named after OpenGL functions. Those functions pointers are NULL during startup, and “initializing” a loader essentially sets them at runtime. The main confusion - what many people misunderstand - it that what matter is which loader the imgui_impl_opengl3.cpp COMPILATION UNIT sees. And because we don’t attempt to initialize the loader ourselves, the user application needs to initialize the same loader on their side too (*). What your snippets omit is telling the opengl3.cpp backend which loader to use. There is a define for that. It’s not possible to make a runtime option because in a same compilation unit, two loaders would conflicts since their headers provide defines and function pointers. In a same project it is technically possible to have multiple loaders (not particularly useful but i imagine in megaapps with many librairies it’s probable that it happens). Conservely there is not added value to using user’s loader or any specific loader. We just somehow need those opengl defines and function pointers, regardless of where they come from (**) Adding to the confusion the fact that is that define is omitted, we attempt to detect a loader based on available include paths. In retrospect maybe this wasn’t a good idea as it can make things confusing for users. You can’t rely on autodetection if your include paths contains other loaders. From vcpkg point of view, each loader should be its own library and the user should still be responsible for initializing it. Its annoying. (*) Last time I checked none of the loader had issue initializing more than once, so I was thinking maybe if imgui_impl_opengl3 did also try to initlaize the loader it sees, it would decrease number of issues (but essentially it’ll make cases where user think they are using loader A but backend actually see loader B “silently work” instead of “fail”. That’s quite debatable) (**) Another solution may be to bite the bullet and develop/embed our own loader OR find a loader we can embed into the backend and get done with it…..
ocornut commented 2021-08-03 09:20:52 +00:00 (Migrated from github.com)

From vcpkg point of view, each loader should be its own library and the user should still be responsible for initializing it.

There are two ways you could go about this. If you can somehow detect that GLAD is being used then vcpkg could define
IMGUI_IMPL_OPENGL_LOADER_GLAD.
Otherwise it would need a dummy library eg “-loader-glad” that would both set this define and drag the actual GLAD library.

I’m tempted to recommend we could investigate the solution of embedding our own loader and not supporting/requiring a user loader…. Would simplify many things for users (with and without vcpkg).

> From vcpkg point of view, each loader should be its own library and the user should still be responsible for initializing it. There are two ways you could go about this. If you can somehow detect that GLAD is being used then vcpkg could define IMGUI_IMPL_OPENGL_LOADER_GLAD. Otherwise it would need a dummy library eg “-loader-glad” that would both set this define and drag the actual GLAD library. I’m tempted to recommend we could investigate the solution of embedding our own loader and not supporting/requiring a user loader…. Would simplify many things for users (with and without vcpkg).
ocornut commented 2021-08-03 09:43:47 +00:00 (Migrated from github.com)

If we decided that imgui_impl_opengl3 always initialized the loader it knows about, it would mean that a system like vcpkg could also decide that adding imgui_impl_opengl3 would automatically drag and enforce a certain loader (whichever you choose) and set the define for it, user won’t have an extra init call to do.

Even if user app used another loader it would work then.

If we decided that imgui_impl_opengl3 always initialized the loader it knows about, it would mean that a system like vcpkg could also decide that adding imgui_impl_opengl3 would automatically drag and enforce a certain loader (whichever you choose) and set the define for it, user won’t have an extra init call to do. Even if user app used another loader it would work then.
NancyLi1013 commented 2021-08-04 06:57:02 +00:00 (Migrated from github.com)

@ocornut

Thanks for your so detailed information and suggestion to solve the problem. I think we should set the define for it according to a certain loader.

@ocornut Thanks for your so detailed information and suggestion to solve the problem. I think we should set the define for it according to a certain loader.
ocornut commented 2021-08-18 15:25:52 +00:00 (Migrated from github.com)

Update: we decided to bite the bullet and we (and by we I mean @rokups) are working toward embedding our own minimalist OpenGL loader into the backend, in order to put in end to that endless amount of confusion/misery caused by the OpenGL loaders.

We already have a version working and we'll either aim to use it in 1.84 or right after 1.84 is released.

TL;DR; ihmo don't put effort into solving this on your end now.

Update: we decided to bite the bullet and we (and by we I mean @rokups) are working toward embedding our own minimalist OpenGL loader into the backend, in order to put in end to that endless amount of confusion/misery caused by the OpenGL loaders. We already have a version working and we'll either aim to use it in 1.84 or right after 1.84 is released. TL;DR; ihmo don't put effort into solving this on your end now.
ocornut commented 2021-08-19 14:31:40 +00:00 (Migrated from github.com)

Should now be solved and made much simpler by #4445

Should now be solved and made much simpler by #4445
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
ocornut/imgui#4390
No description provided.