pthom / imgui_bundle

Dear ImGui Bundle: an extensive set of Ready-to-use widgets and libraries, based on ImGui. Start your first app in 5 lines of code, or less. Whether you prefer Python or C++, this pack has your back!
https://pthom.github.io/imgui_bundle/
MIT License
590 stars 62 forks source link

Glfw Error 65542: WGL: The driver does not appear to support OpenGL #206

Closed markusgritsch closed 2 months ago

markusgritsch commented 2 months ago

Hi, I installed imgui_bundle on my Windows 10 (version 22H2) laptop which has integrated Intel HD Graphics 3000. When starting demo_imgui_bundle.exe I get the following traceback:

C:\Users\mgr>demo_imgui_bundle.exe
For information, demos sources are available in C:/Users/mgr/AppData/Roaming/Python/Python310/site-packages/imgui_bundle/demos_python
Glfw Error 65542: WGL: The driver does not appear to support OpenGL
throw runtime_error: BackendGlfw::CreateWindow / glfwCreateWindow failed                 at D:\a\imgui_bundle\imgui_bundle\external\hello_imgui\hello_imgui\src\hello_imgui\internal\backend_impls\backend_window_helper\glfw_window_helper.cpp:98
Traceback (most recent call last):
  File "C:\Program Files\Thonny\lib\runpy.py", line 196, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "C:\Program Files\Thonny\lib\runpy.py", line 86, in _run_code
    exec(code, run_globals)
  File "C:\Users\mgr\AppData\Roaming\Python\Python310\Scripts\demo_imgui_bundle.exe\__main__.py", line 7, in <module>
  File "C:\Users\mgr\AppData\Roaming\Python\Python310\site-packages\imgui_bundle\demos_python\demo_imgui_bundle.py", line 131, in main
    immapp.run(runner_params=runner_params, add_ons_params=addons)
RuntimeError: BackendGlfw::CreateWindow / glfwCreateWindow failed

All the demos from https://www.dearimgui.com/binaries/imgui-demo-binaries-20240105.zip are running fine, includging example_glfw_opengl2.exe and example_glfw_opengl3.exe.

Any suggestions what to try next?

pthom commented 2 months ago

Maybe you should try to update your driver.

I saw some results on Google concering minecraft: https://www.google.com/search?q=Intel+HD+Graphics+Glfw+Error+65542%3A+WGL%3A+The+driver+does+not+appear+to+support+OpenGL&sca_esv=faf3bf626897cb5c&sca_upv=1&sxsrf=ACQVn0-YQCEz5nc4cCUDf2le4QMk4qj-Vg%3A1713611514070&source=hp&ei=-qIjZtf6AY6JkdUPhfqfUA&iflsig=ANes7DEAAAAAZiOxCrdbZetDtahmqN31KuDUS-v6oweR&ved=0ahUKEwjX386s1NCFAxWORKQEHQX9BwoQ4dUDCBU&uact=5&oq=Intel+HD+Graphics+Glfw+Error+65542%3A+WGL%3A+The+driver+does+not+appear+to+support+OpenGL&gs_lp=Egdnd3Mtd2l6IlVJbnRlbCBIRCBHcmFwaGljcyBHbGZ3IEVycm9yIDY1NTQyOiBXR0w6IFRoZSBkcml2ZXIgZG9lcyBub3QgYXBwZWFyIHRvIHN1cHBvcnQgT3BlbkdMSABQAFgAcAB4AJABAJgBAKABAKoBALgBA8gBAPgBAvgBAZgCAKACAJgDAJIHAKAHAA&sclient=gws-wiz

markusgritsch commented 2 months ago

Thanks for the quick reply. I also saw these suggestions when googling for this error, however, the Intel program says I'm already on the latest available driver for my hardware, so this didn't help.

It is further confusing, that the glfw precompiled demos from ocornut are running fine.

markusgritsch commented 2 months ago

I installed https://github.com/nimgl/nimgl for Nim which includes the libraries imgui and glfw. In the example https://github.com/nimgl/nimgl/blob/master/examples/timgui.nim I had to set GLFWContextVersionMinor to 1 and comment out the line containing GLFW_OPENGL_CORE_PROFILE. After these changes, the example runs fine: grafik So my graphics card/driver supports OpenGL, as already supposed because of the working precompiled cpp imgui-demos.

I really wonder, what pyGLFW does differently, which causes the problems on my machine. I tried setting

    glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 3)
    glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 1)

but to no avail.

pthom commented 2 months ago

Hi,

If you compile from source, you can try to edit external/hello_imgui/hello_imgui/src/hello_imgui/internal/backend_impls/opengl_setup_helper/opengl_setup_glfw.cpp

There is a good chance you may find a setting that works for you there. Please keep me informed if you do find a solution.

See instructions to compile from source here: https://pthom.github.io/imgui_bundle/install-instructions.html

markusgritsch commented 2 months ago

I'm a bit reluctant to install everything to compile imgui_bundle from source on my laptop.

So when glfw is compiled to a .dll, there is no way to set glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 1) from the Python code, correct?

Lines 34 and 35 in https://github.com/pthom/hello_imgui/blob/master/src/hello_imgui/internal/backend_impls/opengl_setup_helper/opengl_setup_glfw.cpp will definitely prevent it from running on my laptop. Is there any particular reason it is set to these values? The imgui example from ocornut does set it only to GL 3.0: https://github.com/ocornut/imgui/blob/master/examples/example_glfw_opengl3/main.cpp#L62

pthom commented 2 months ago

Since imgui bundle / hello imgui handles glfw initialization and Window creation anything you do before would be discarded upon calling glfwInit()

See https://www.glfw.org/docs/latest/window.html#window_hints:

There are a number of hints that can be set before the creation of a window and context. Some affect the window itself, others affect the framebuffer or context. These hints are set to their default values each time the library is initialized with glfwInit.

Is there any particular reason it is set to these values? The imgui example from ocornut does set it only to GL 3.0

Making sure that the system works on most machines and OS was a very difficult task (especially given that I target mac, windows, linux, iOS, Android, emscripten, etc.). The reason the code requires more than 3.0 is probably because some shaders require a more recent version. OpenGL 3.3 dates back from 2010 and I'm reluctant to lower this value in the default setup, because I'm afraid this might break on some other user's machines.

I might someday add an option to set this up before starting an application.

markusgritsch commented 2 months ago

I completely understand your concerns changing the defaults.

What remains a mystery to me is, why the pyGLFW example at the bottom on this page https://github.com/FlorianRhiem/pyGLFW still gives me this error C:\Users\mgr\AppData\Roaming\Python\Python310\site-packages\glfw\__init__.py:914: GLFWError: (65542) b'WGL: The driver does not appear to support OpenGL' even if I add

    glfw.window_hint(glfw.CONTEXT_VERSION_MAJOR, 3)
    glfw.window_hint(glfw.CONTEXT_VERSION_MINOR, 1)

between glfw.init() and glfw.create_window(...).

Maybe I should try and ask the creator of PyGLFW.

pthom commented 2 months ago

PyGLFW only provides bindings, I don't think the issue is there.

The error is probably inside the C++ library GLFW. You should try first to write a simple C++ program, such as for example:

#include <GLFW/glfw3.h>
#include <stdio.h>

int main(void)
{
    GLFWwindow* window;

    // Initialize the library
    if (!glfwInit())
    {
        fprintf(stderr, "Failed to initialize GLFW\n");
        return -1;
    }

    // Set OpenGL version, for example, OpenGL 3.3
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
    glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);

    // Create a windowed mode window and its OpenGL context
    window = glfwCreateWindow(640, 480, "Hello OpenGL", NULL, NULL);
    if (!window)
    {
        glfwTerminate();
        fprintf(stderr, "Failed to create GLFW window\n");
        return -1;
    }

    // Make the window's context current
    glfwMakeContextCurrent(window);

    // Loop until the user closes the window
    while (!glfwWindowShouldClose(window))
    {
        // Render here

        // Swap front and back buffers
        glfwSwapBuffers(window);

        // Poll for and process events
        glfwPollEvents();
    }

    glfwTerminate();
    return 0;
}

And see if you can reproduce the error / correct the error from here.

markusgritsch commented 2 months ago

Thank you for your reply. I compiled glfw myself (details here: https://github.com/FlorianRhiem/pyGLFW/issues/79#issuecomment-2068171168) and everything including the supplied examples works fine. Replacing one example with your given testprogram works, if I set GLFW_CONTEXT_VERSION_MINOR to 1 and comment out the line containing GLFW_OPENGL_CORE_PROFILE. It also works when I comment all the glfwWindowHint() lines. grafik

pthom commented 2 months ago

Hi,

I added advanced options to set more OpenGL parameters:

The API looks like:

    runner_params = hello_imgui.RunnerParams()
    runner_params.callbacks.show_gui = gui
    runner_params.platform_backend_type = hello_imgui.PlatformBackendType.glfw

    runner_params.renderer_backend_options.open_gl_options = hello_imgui.OpenGlOptions()
    runner_params.renderer_backend_options.open_gl_options.major_version = 3
    runner_params.renderer_backend_options.open_gl_options.minor_version = 2
    runner_params.renderer_backend_options.open_gl_options.glsl_version = "#version 130"
    runner_params.renderer_backend_options.open_gl_options.use_core_profile = True

    immapp.run(runner_params)

And the full API for the options is: https://github.com/pthom/imgui_bundle/blob/38e07526bc095037bcb55f92933e487fa54b0476/bindings/imgui_bundle/hello_imgui.pyi#L2352-L2383

You can see an example here: https://github.com/pthom/imgui_bundle/blob/main/bindings/imgui_bundle/demos_python/sandbox/sandbox_custom_opengl_version.py

I will not release a version of the ImGui bundle soon, but you can download wheels with those patches here: https://github.com/pthom/imgui_bundle/actions/runs/8797315173

markusgritsch commented 2 months ago

Hi Pascal, thank you for adding this option. I installed the .whl, but as expected it does not solve my problem I have on my laptop. It's really annoying, because I can compile and successfully run the ImGUI examples if I set GLFW to GL 3.1, but when OpenGL is accessed from Python via ctypes, a different GL implementation/DLL seems to get loaded. And I am really lost, how this can happen.

In the other issue https://github.com/FlorianRhiem/pyGLFW/issues/79 I tried this minimal pyglet example

import pyglet
window = pyglet.window.Window()

which gives the following traceback on my laptop:

Traceback (most recent call last):
  File "C:\Users\mgr\Downloads\examples\opengl\opengl_scissor.py", line 14, in <module>
    window = pyglet.window.Window(width=500, height=500)
  File "C:\Users\mgr\AppData\Roaming\Python\Python310\site-packages\pyglet\window\win32\__init__.py", line 104, in __init__
    super(Win32Window, self).__init__(*args, **kwargs)
  File "C:\Users\mgr\AppData\Roaming\Python\Python310\site-packages\pyglet\window\__init__.py", line 583, in __init__
    self._create_projection()
  File "C:\Users\mgr\AppData\Roaming\Python\Python310\site-packages\pyglet\window\__init__.py", line 591, in _create_projection
    shader.Shader(self._default_vertex_source, 'vertex'),
  File "C:\Users\mgr\AppData\Roaming\Python\Python310\site-packages\pyglet\graphics\shader.py", line 795, in __init__
    shader_id = glCreateShader(shader_type)
  File "C:\Users\mgr\AppData\Roaming\Python\Python310\site-packages\pyglet\gl\lib_wgl.py", line 66, in __call__
    return self.func(*args, **kwargs)
  File "C:\Users\mgr\AppData\Roaming\Python\Python310\site-packages\pyglet\gl\lib.py", line 25, in MissingFunction
    raise MissingFunctionException(name, requires, suggestions)
pyglet.gl.lib.MissingFunctionException: glCreateShader is not exported by the available OpenGL driver.  OpenGL 2.0 is required for this functionality.

So pyglet does not even see a GL 2.0 capable driver.

Do you have any idea how I can investigate, which dll at which location ctypes is using?

pthom commented 2 months ago

Hum, If it is the DLL loading that causes issues, there is a possible explanation inside imgui_bundle.

Let me explain. Below is a summary of the structure of the Dear ImGui Bundle package (Here under macOS, but under Windows, you will find DLLs instead of dylib)

v312/lib/python3.12/site-packages/imgui_bundle/
    ├── __init__.py                    # will call _glfw_set_search_path
    ├
    ├── libglfw.3.3.dylib              # the glfw library that is linked to imgui_bundle
    ├── libglfw.3.dylib                # and that *must* be used otherwise,         
    ├── libglfw.3.so                   # serious ABI issues will arise
    ├── libglfw.dylib
    ├
    ├── _glfw_set_search_path.py       # will set the dll search path for libglfw to this directory
    ├
    ├── imgui/
    │     ├── ...
    ├── implot/
    ├── _imgui_bundle.cpython-312-darwin.so  # the imgui_bundle python module 
    └── ...

Since _imgui_bundle.cpython-312-darwin.so is linked to glfw, it has to use the version of GLFW with which it is linked. It is impossible to switch for another one.

But I'm not sure this has something to do with your pyglet issue. But maybe pyglet uses a similar technique.

_glfw_set_search_path uses a utility provided by pyGlfw to set the dll search path:

# Part of ImGui Bundle - MIT License - Copyright (c) 2022-2023 Pascal Thomet - https://github.com/pthom/imgui_bundle

def _glfw_set_search_path() -> None:
    """Sets os.environ["PYGLFW_LIBRARY"] so that glfw provided by pip uses our glfw library.

    venv/lib/python3.9/site-packages/glfw/library.py

    if os.environ.get('PYGLFW_LIBRARY', ''):
        try:
            glfw = ctypes.CDLL(os.environ['PYGLFW_LIBRARY'])
        except OSError:
            glfw = None

    """
    import os
    import platform

    this_dir = os.path.dirname(__file__)
    if platform.system() == "Darwin":
        lib_file = "libglfw.3.dylib"
    elif platform.system() == "Windows":
        lib_file = "glfw3.dll"
    elif platform.system() == "Linux":
        lib_file = "libglfw.so.3"
    else:
        msg = f"Please implement set_pip_glfw_search_path() for your os: {platform.system()}\n"
        raise NotImplementedError(msg)
    os.environ["PYGLFW_LIBRARY"] = f"{this_dir}/{lib_file}"
markusgritsch commented 2 months ago

The thing is, I have compiled GLFW from sources myself, static library and .dll, and the examples included with GLFW are running fine, also when they are linked dynamically to the self-compiled glfw3.dll. See https://github.com/FlorianRhiem/pyGLFW/issues/79#issuecomment-2068171168

But even when setting the PYGLFW_LIBRARY environment variable to this self-compiled .dll, I get the error when calling glfw.create_window. Florian Rhiem provided a simple ctypes based example to rule out any issue with pyGLFW, and it does not work, see https://github.com/FlorianRhiem/pyGLFW/issues/79#issuecomment-2069837347

markusgritsch commented 2 months ago

I resolved my issue. Details can be found here: https://github.com/FlorianRhiem/pyGLFW/issues/79#issuecomment-2074195675

When I add

    runner_params.renderer_backend_options.open_gl_options = hello_imgui.OpenGlOptions()
    runner_params.renderer_backend_options.open_gl_options.major_version = 3
    runner_params.renderer_backend_options.open_gl_options.minor_version = 1
    runner_params.renderer_backend_options.open_gl_options.glsl_version = "#version 130"
    runner_params.renderer_backend_options.open_gl_options.use_core_profile = False

to the examples, they are running fine on my Latop :)

As already mentioned, Dear ImGUI is a bit more conservative in their example here https://github.com/ocornut/imgui/blob/master/examples/example_glfw_opengl3/main.cpp#L62

You said your are a bit reluctant to change the default for imgui-bundle because some shaders need a newer version.

Are you going to add the open_gl_options lines to all the examples of imgui-bundle then, maybe even with the conservative requirements identical to the Dear ImGUI example? This way users would at least see, that this might be the problem, if the example is not working for them on older hardware.

pthom commented 2 months ago

What OS are you running ? Windows ?

markusgritsch commented 2 months ago

Yes, Windows 10.

pthom commented 2 months ago

No, I will not modify the examples. I don't want to confuse new users with low level graphics settings. However, at some point I will add a failure check after the call to CreateWindow, And retry with more conservative parameters.

markusgritsch commented 2 months ago

Good idea.

Thank you again for your help!

pthom commented 2 months ago

@markusgritsch

I pushed a modification on the repo. Two important things you should know:

See https://github.com/pthom/imgui_bundle/blob/323fec742673cbe9ae1334a882e65ec3f3150508/bindings/imgui_bundle/hello_imgui.pyi#L2352-L2411

The ability to set it in any parent folder should solve your issue for all of the examples with only one setting file.

I could not get a version that tries two different settings. This is too dangerous and some backends will choke and never recover if given bad parameters at the start.

Wheels should be ready in a few hours here: https://github.com/pthom/imgui_bundle/actions/runs/8832657513

markusgritsch commented 2 months ago

The idea with the hello_imgui.ini file is cool, but it does not work for me. When starting the examples, I do not get a program window, nor any error message.

When I have no .ini file and use

    runner_params.renderer_backend_options.open_gl_options = hello_imgui.OpenGlOptions()
    runner_params.renderer_backend_options.open_gl_options.major_version = 3
    runner_params.renderer_backend_options.open_gl_options.minor_version = 1
    runner_params.renderer_backend_options.open_gl_options.glsl_version = "130"
    runner_params.renderer_backend_options.open_gl_options.use_core_profile = False

it works, but when I instead place this hello_imgui.ini file in the folder

[OpenGlOptions]
GlslVersion = 130
MajorVersion = 3
MinorVersion = 1
UseCoreProfile = False
UseForwardCompat = False

I get nothing.

pthom commented 2 months ago

Well, well, well, tracking that was not easy. I suspect it is related to a compiler bug in Visual Studio.

Here is the fix I had to apply : https://github.com/pthom/hello_imgui/compare/4ace340ef854442fa371cca2beb4d3cd6322f299...a2c3617dcc6022ec900fc411cc01c9be6c27a453#diff-c6e964d4f37662ef39e5cbacd4b57597f1862cbc9786ee991f98ed55c77938e6

Replacing a generic lambda

template<typename T>
auto _readIniValueInParentFolders = []
    (const std::string& sectionName, const std::string& valueName) -> std::optional<T>

by a generic function

template <typename T>
std::optional<T> _readIniValueInParentFolders
    (const std::string& sectionName, const std::string& valueName)

somehow "fixed" the issue

pthom commented 2 months ago

See https://stackoverflow.com/questions/78389519/msvc-compiler-bug-with-c-generic-lambda-now-with-minimal-repro?noredirect=1#comment138198306_78389519

I confirm: This was due to a compiler bug. A quite scary one actually.

markusgritsch commented 2 months ago

Ok, I can test again, when a new wheel becomes available.

pthom commented 2 months ago

Ok, I can test again, when a new wheel becomes available.

https://github.com/pthom/imgui_bundle/actions/runs/8834742423

markusgritsch commented 2 months ago

Great! Workls like a charm!

Thanks a lot for all your effort.