Skip to content
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

OpenGL backend now embeds its own GL loader (imgui_impl_opengl3_loader.h) #4445

Closed
ocornut opened this issue Aug 19, 2021 · 24 comments
Closed

Comments

@ocornut
Copy link
Owner

ocornut commented Aug 19, 2021

TL;DR;

Our GL backend now embed its own minimal GL loader (embedded file; full source repo)
User/application don't need to configure anything related to GL loader.
User/application can use their own GL loader of choice regardless of what our backend does.
Thanks @rokups!

What is an OpenGL loader

Desktop OpenGL doesn't have standard portable header/libs files for all features GL offers.
Helper libraries are often used for this purpose. There are many of them: glew, glad, glbinding, glext to name a few (easy to recreate one). Those libraries tend to two things:

  • They provide the defines/enums used by modern GL features and/or variety of extensions.
  • They provide function pointers that one can call to access those GL features. During initialization the library loads e.g. the OpenGL DLL and assign those pointers to available functions.

WebGL and GL ES do not suffer from this as the headers and libraries are better standardized.

What our imgui_impl_opengl backend did (and the problems)

Until recently, the OpenGL3 backends and examples made a best effort to support variety of GL loaders. This turned to be a mistake which created confusion for users (many of them being newcomers to OpenGL, to Dear ImGui or to C++ programming in general), as this support relied on compile-time defines, plus an attempt at detecting available system includes (which I also now firmly regret).

To be able to provide examples that would compile out of the box we had to include a loader in the examples folder. We included gl3w, which was picked at the time because its output was small and neat, but as many existing GL users used another loader it was confusing for them.

What frequently happened is user's existing application used loader X and compiled our backend in a way that used loader Y which was either not initialized, either not linked. This made integrating Dear ImGui in an established OpenGL codebase more confusing.

Our setup, which required the user to provide and initialize (on their side) the GL loader that the backend used, unwillingly contributed to perpetuate a common misconception that "an application can't use multiple GL loaders". A loader is merely a bunch of defines and function pointers, of course we can!

Things got even more complicated as package managers like vcpkg are trying to provide a seamless experience where the user can grab e.g. "imgui" + "opengl3 backend" but that needed to drag loader libraries into the mix and they would need to be initialized by a call that vcpkg couldn't magically inject into user app. (See their issue microsoft/vcpkg#14753)

What are are now doing

(This is the work of @rokups)

We decided to simply embed and use own loader, solely for usage by imgui_impl_opengl3.cpp.
The new loader is backends/imgui_impl_opengl3_loader.h and automatically used by our backend.
If you update your backends by copying files, you'll have to grab this file too.

It means that it doesn't matter which GL loader your existing application is using. We don't care. We have our own. Both can cohabit.

Because we are committed to our bloat free approach, we had concerns with adding a "regular" loader inside backends/ as most available loaders are now a bit large. We forked gl3w into gl3w_stripped which greps for symbols used by imgui_impl_opengl3.cpp and only include the one we need. As a result, backends/imgui_impl_opengl3_loader.h is only about ~32 KB of source file and compiles to almost nothing.

That's all!

(
PS: on the unlikely case that your app ended up using our old copy of gl3w directly from our repository in examples/libs/gl3w: (1) You may access gl3w original repository https://github.com/skaslev/gl3w, (2) You may grab the files from dear imgui 1.83 repo, or (3) You may look at https://github.com/dearimgui/gl3w_stripped which is our fork of gl3w that handle filtering.
)

Links

Here's a partial list of issues related to compiling/linking/configuring GL loaders:

#4390 #4279 #4428 #3986 #3860 #3769 #3736 #3507 #3330 #3246 #2798 #3061 #2919 #2870 #2806 #2785 #2444 #2180 #2178 #2002 #2001 #1988 #1956 #1806 #1576 #880 #483

ocornut pushed a commit that referenced this issue Aug 19, 2021
…use it in SDL/GLFW examples. (#4445)

Loader repository at https://github.com/dearimgui/gl3w_stripped
Removed support for using custom loaders in examples/opengl3 backend
@ocornut ocornut changed the title OpenGL backend now embed its own GL loader (imgui_impl_opengl3_loader.h) OpenGL backend now embeds its own GL loader (imgui_impl_opengl3_loader.h) Aug 19, 2021
@metarutaiga
Copy link

metarutaiga commented Aug 20, 2021

This is my OpenGL ES 3.2 Loader. (Lazy import)
https://github.com/metarutaiga/TensorFlowLiteReduce/blob/master/third_party/GLES3/gl3_loader.c
https://github.com/metarutaiga/xxGraphic/blob/master/internal/xxGraphicInternalGL.cpp

1.It can prevent to run a null pointer calling.
2.Not to need include its header, like a library linking.
3.To add a function needs one line only.
4.It can reduce code size because it linked we need functions.

@nitrix
Copy link

nitrix commented Aug 22, 2021

This is great news and will help other programming language communities re-use the official C++ backend instead of each re-implementing their own due to problems with some loaders unable to cross the FFI boundary. Looks significantly simpler now, thank you.

@parbo
Copy link

parbo commented Aug 23, 2021

After I updated to the version with this, the images I load with my (complete) gl3w loader end up black. If I replace #include "imgui_impl_opengl3_loader.h" with my own gl3w.h then it works. Am I not supposed to be able to create GL texture id's with one loader and use them with the new embedded one?

@ocornut
Copy link
Owner Author

ocornut commented Aug 23, 2021

Thanks for reporting @parbo. I can't understand how this would have an impact. The loader are essentially merely function pointers to GL functions and a bunch of defines. We also made sure that our forked-stripped-gl3w used non conflicting symbols so gl3w could still be used...
But it is arguably troubling if just replacing the header included from imgui_impl_opengl3.cpp works.
Could there be a difference in the #ifdef paths taken by the backend?

@parbo
Copy link

parbo commented Aug 23, 2021

That was my theory too, but I didn't find anything obvious. I will try some more tomorrow..

@MachSilva
Copy link

When I updated it too and then executed the program, I got some memory access violations on Windows during the loader initialization. However, when I tried to compile the same project on Linux, I got "multiple definitions for gl3wProcs" during linking. It appears that the definitions for the union GL3WProcs are different in the files gl3w.c and imgui_impl_opengl3.h. Could it be the reason for your black images?

@ocornut
Copy link
Owner Author

ocornut commented Aug 23, 2021

OK it looks like we broke something (@rokups?) the symbols in that file are called gl3wProcs and not static, it might conflict with another copy of gl3w.

@ocornut
Copy link
Owner Author

ocornut commented Aug 23, 2021

@parbo @MachSilva in imgui_impl_opengl3_loader.h

Can you try renaming gl3wProcs to imgl3wProcs (using CASE SENSITIVE, FULL WORD search & replace to not mess with the union name).

It should be those lines:

GL3W_API extern union GL3WProcs imgl3wProcs;
...
#define glActiveTexture                  imgl3wProcs.gl.ActiveTexture
#define glAttachShader                   imgl3wProcs.gl.AttachShader
+ 50 others
...
GL3W_API union GL3WProcs imgl3wProcs;
...
 imgl3wProcs.ptr[i] = proc(proc_names[i]);

@MachSilva
Copy link

Yes. It solved my problem on both platforms. Thank you.

@parbo
Copy link

parbo commented Aug 24, 2021

It does indeed fix my problems too!

@ocornut
Copy link
Owner Author

ocornut commented Aug 24, 2021

Merged 4c22b3e to fix this.

AnClark pushed a commit to AnClark/imgui-vst-mod that referenced this issue Aug 30, 2021
…use it in SDL/GLFW examples. (ocornut#4445)

Loader repository at https://github.com/dearimgui/gl3w_stripped
Removed support for using custom loaders in examples/opengl3 backend
AnClark pushed a commit to AnClark/imgui-vst-mod that referenced this issue Aug 30, 2021
AnClark pushed a commit to AnClark/imgui-vst-mod that referenced this issue Aug 30, 2021
AnClark pushed a commit to AnClark/imgui-vst-mod that referenced this issue Aug 30, 2021
…use it in SDL/GLFW examples. (ocornut#4445)

Loader repository at https://github.com/dearimgui/gl3w_stripped
Removed support for using custom loaders in examples/opengl3 backend
AnClark pushed a commit to AnClark/imgui-vst-mod that referenced this issue Aug 30, 2021
AnClark pushed a commit to AnClark/imgui-vst-mod that referenced this issue Aug 30, 2021
@Slluxx
Copy link

Slluxx commented Sep 3, 2021

the loader is including "<dlfcn.h>", which is not present on my embedded system. I am not sure how to resolve this issue. Am i stuck on an earlier version?

@ocornut
Copy link
Owner Author

ocornut commented Sep 3, 2021

@Slluxx which loader did you use that worked in the earlier version? Whats your embedded system and how did the previous loader access the functions?

@Slluxx
Copy link

Slluxx commented Sep 3, 2021

i was using imgui v1.77, which did not have a loader file. If it did but hidden, then im unsure about the details.
Im using the nintendo switch, glfw and opengl3.

@ocornut
Copy link
Owner Author

ocornut commented Sep 3, 2021 via email

ocornut added a commit that referenced this issue Sep 7, 2021
…se of another loader in same compilation unit. (#4445, #4514)
@feipiefei
Copy link

could you please teach me how to solve this problem
""" fatal error C1189: #error: "Cannot detect OpenGL loader!" """,

@ocornut
Copy link
Owner Author

ocornut commented Sep 21, 2021

@feipiefei This is not a problem anymore with latest version.

@Slluxx
Copy link

Slluxx commented Dec 20, 2021

It always used a loader. Add a printf in the init function to display the gl_loader variable and find which one you used. I would like to get this fixed but we can’t do it without the help of affected users.

sorry for the super late reply, i havent tried to update since then.
gl_loader is "glad". now i am struggeling to figure out how to get it back working

@ocornut
Copy link
Owner Author

ocornut commented Dec 20, 2021

Well we should look how GLAD worked on your system and mimick that.
What's your Nintendo Switch SDK name/version?
Maybe get back to a old setup with GLAD and see what code GLAD calls.

If I skim at GLAD sources (https://glad.dav1d.de/)
It seems to always use <dlfcn.h> on non-Windows systems, so I think the assumption that dlfcn.h is not available on your compiler setup may be wrong...

@Slluxx
Copy link

Slluxx commented Dec 20, 2021

I am just using a plain old hacked switch together with a toolchain from devkitpro.
There are a few examples on how to work with GLAD on the system, one being this.

In my 1.77 code, i use imgui_impl_opengl3 and imgui_impl_glfw and none of them seem to include <dlfcn.h>.
Maybe i am just doing something super wrong? all that glad, glfw, opengl, gles, ... stuff is very confusing.

I wish markdown had spoilers. Anyway, this code works on my console.

#include "imgui/imgui.h"
#include "imgui/imgui_internal.h"
#include "imgui/imgui_impl_glfw_switch.h" // dont mind "custom" the filename. there is nothing custom in the file.
#include "imgui/imgui_impl_opengl3.h"

#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <switch.h>
#include <chrono>
#include <set>
#include <thread>
#include <string>
#include <vector>
#include <iterator>
#include <map>
#include <dirent.h>

#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h>
#include <glad/glad.h>
#define GLM_FORCE_PURE
#define GLM_ENABLE_EXPERIMENTAL
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtx/rotate_vector.hpp>
#include <glm/mat4x4.hpp>
#include <glm/vec3.hpp>
#include <glm/vec4.hpp>

#include "helper.hpp"
#include "IconsFontAwesome4.h"
      // Init glfw
    glfwSetErrorCallback(errorCallback);
    glfwInitHint(GLFW_JOYSTICK_HAT_BUTTONS, GLFW_FALSE);
    if (!glfwInit())
        return false;

    const char *glsl_version = "#version 430 core";
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    GLFWwindow *window = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "test", nullptr, nullptr);
    if (!window)
        glfwTerminate();

    glfwSetInputMode(window, GLFW_STICKY_KEYS, GLFW_TRUE);
    glfwMakeContextCurrent(window);
    gladLoadGLLoader((GLADloadproc)glfwGetProcAddress);
    glfwSwapInterval(1);


    // imgui init
    // ...
    ImGui_ImplGlfw_InitForOpenGL(window, true);
    ImGui_ImplOpenGL3_Init(glsl_version);

    // Main loop
    while (!glfwWindowShouldClose(window))
    {
        glfwPollEvents();
        ImGui_ImplOpenGL3_NewFrame();
        ImGui_ImplGlfw_NewFrame();
        ImGui::NewFrame();

        // main window code

        // Rendering
        ImGui::Render();
        int display_w, display_h;
        glfwGetFramebufferSize(window, &display_w, &display_h);
        glViewport(0, 0, display_w, display_h);
        glClearColor(0.45f,  0.55f,  0.60f, 1.00f);
        glClear(GL_COLOR_BUFFER_BIT);
        ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());

        glfwSwapBuffers(window);
    }

    // Cleanup
    ImGui_ImplOpenGL3_Shutdown();
    ImGui_ImplGlfw_Shutdown();
    ImGui::DestroyContext();
    glfwDestroyWindow(window);
    glfwTerminate();
    return 0;

@ocornut
Copy link
Owner Author

ocornut commented Dec 20, 2021

Where's the code for GLAD.c ?
Glad.c here seems to always include dlfnc.h

We should probably include a way to optional pass in a function loader to the OpenGL backend, may help some users, but right now I don't see how things would compile.

@Slluxx
Copy link

Slluxx commented Dec 20, 2021

@ocornut here it is

@ocornut
Copy link
Owner Author

ocornut commented Jul 1, 2022

@ocornut here it is

@Slluxx Somebody would need to study that version of Glad and see how the logic can be ported to our GL3W, find how to make it compile and if we can make it possible for your code to initialize it with a custom GL3WGetProcAddressProc function.
This should be done by someone using your devkit.

@ocornut
Copy link
Owner Author

ocornut commented Sep 14, 2022

Closing this as idle (and the big issue/news is done).

@Slluxx I am open to add support for a custom loader function, but someone using that homebrew Switch SDK would need to investigate this and submit the PR.

@ocornut ocornut closed this as completed Sep 14, 2022
ocornut pushed a commit that referenced this issue Feb 14, 2023
…2.x (#6154, #4445, #3530)

GL_MAJOR_VERSION and GL_MINOR_VERSION are available on GL 3.0 and above.
So we have to parse GL_VERSION under GL 2.x
Reference https://www.khronos.org/opengl/wiki/OpenGL_Context#Context_information_queries
Regressed since 459de65
See #3530
ocornut added a commit that referenced this issue Mar 15, 2023
ocornut pushed a commit that referenced this issue Oct 5, 2023
vug added a commit to vug/graphics-app-boilerplate that referenced this issue Feb 13, 2024
ocornut pushed a commit to dearimgui/gl3w_stripped that referenced this issue May 7, 2024
(reworked 2024-05-07 to try unfucking this project)

Clean up generator arguments and ignore symbols mentioned in comments, but unused in source code.

(reworked 2024-05-07 to try unfucking this project)
# Conflicts:
#	gl3w_gen.py

Change name of gl3wProcs to avoid symbol collisions.

ocornut/imgui#4445 (comment)

# Conflicts:
#	gl3w_gen.py

Simplify API scan and add extra_symbols.txt for including additional symbols.

# Conflicts:
#	gl3w_gen.py
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants