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 error when restoring the state of the OpenGL context #6220

Closed
Cyphall opened this issue Mar 3, 2023 · 4 comments
Closed

OpenGL error when restoring the state of the OpenGL context #6220

Cyphall opened this issue Mar 3, 2023 · 4 comments

Comments

@Cyphall
Copy link
Contributor

Cyphall commented Mar 3, 2023

Version/Branch of Dear ImGui:

Version: 1.89
Branch: docking

Back-end/Renderer/Compiler/OS

Back-ends: imgui_impl_glfw.cpp + imgui_impl_opengl3.cpp
Compiler: MSVC
Operating System: Windows 11

My Issue:

There is a bug in imgui_impl_opengl3.cpp at line 579 that may generate the following OpenGL error:
GL_INVALID_VALUE error generated. Program handle does not refer to an object generated by OpenGL.

This error is caused by the following situation:

  1. Create an OpenGL shader (we will call it 123).
  2. Bind the shader and do some rendering
  3. Delete the shader as it is no longer needed. The shader is flagged for deletion but not directly deleted as it is currently bound to the state machine.
  4. Render the ImGui UI.
    In this step, the backend will first backup the currently bound shader using glGetIntegerv(GL_CURRENT_PROGRAM, ...). This will return 123 since our shader is not deleted yet (as it is bound), but is pending deletion.
    The backend will then do its internals, which includes binding its own shaders. This will unbind our shader 123 and since it is pending deletion and no longer used by OpenGL, it will actually be deleted there.
    Once the backend is done with its tasks, it will attempt to rebind the previously bound shader, which is our shader 123. The problem is that in the meantime, this shader has been deleted. This call ends up binding a deleted shader and causing the mentionned OpenGL error.

A way to fix this is to check if the shader is still valid before trying to rebind it:

if (glIsProgram(last_program))
    glUseProgram(last_program);

Note: This bug may also apply to other resources in the backup/restore steps.

@ocornut
Copy link
Owner

ocornut commented Mar 4, 2023

Interesting find. Thanks for the careful report.

I am wondering if it might not be simpler than we call glGetError() once rather than attempt to deal with all possible edge cases here?
Otherwise I’d rather fix situations one by one as they are encountered by real people, like you just did for texture.

@Cyphall
Copy link
Contributor Author

Cyphall commented Mar 4, 2023

The glGetError() idea might not work for cases where people use the Debug Output Callback feature.
In my case, my program is designed to crash at the first OpenGL error caught by this callback (since it is a personal project and does not need any robustness).

Since this bug can only occur for OpenGL objects (shader programs, textures, buffers and a few others), it may be cleaner (but still quick) to just add the handful of necessary if (glIsXXX()).

@Cyphall
Copy link
Contributor Author

Cyphall commented Mar 5, 2023

So it turns out that only Program and Shader objects can be in a "pending deletion" state.
Other objects will simply set the current binding to 0 if they are deleted while being bound.

@ocornut
Copy link
Owner

ocornut commented Mar 6, 2023

Thank you! Merged your fix as 66b7625.

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

2 participants