-
-
Notifications
You must be signed in to change notification settings - Fork 10.4k
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
Restoring OpenGL state after using callbacks #1639
Conversation
@xor2k I understand your intent but I don't understand your solution at all. There are hundreds of GL state, it should be up to the callback to restore whatever state they changed. Setting/restoring a small selection of state because this what your application changes doesn't provide a good solution. If restoring modified state is too much work, you could even provide your own callback to reset the render state to the one required for the imgui render loop, and queue that callback. |
Well, I agree with you about that. However, as far as I can see, there is no way to backup the glVertexAttribPointer state (glGetVertexAttribPointerv at least will not do it) and the configuration, i.e. how many indices there are, and all their other arguments are specific to the draw list shaders, so to properly restore them, the restoration has to be done in the draw list shader code, i.e. the imgui_impl*.cpp. Or am I missing something? |
I guess we could have the renderer expose a function to restore specific state, or split the function to have a full separate backup/setup/restore, or decide of a way for callbacks to communicate that they want a full gpu state restore. For now I'd suggest you add yourself a function with those 6 lines and you can call the function BELOW the I'm interested in those problem because I'm currently refactoring the imgui_impl_xxx files (separating renderer (opengl, directx, vulkan etc.) from platform (glfw, sdl, win32, etc.) and until now I was telling people it is ok to modify those _impl file, and it still is, but I would eventually like those files to cater for more use cases. If you have a fancy engine presumably it wouldn't be a problem for you to just copy that render function in your code and modify it. |
If you make certain changes to the draw list shaders, e.g. you modify an attribute, my 6 lines restore code will be invalidated. Not that I expect this to happen often, but there should be a canonical way to restore certain states of the draw list shaders. The glVertexAttribPointer is a very good starting point: when it is restored, the draw lists can actually be used alongside custom shaders. Below is the test code I am currently using. As you can see, it is directly derived from the draw list code. In addition to this pull request, this code is a compact example of what I would expect the user callback to do. I am thinking of some header listed functions that can be called to save/restore the draw list shader state.
and of course
|
Why do you need a custom shader to render DrawLists, let alone multiple ones? From the linked thread, it does seem like rendering your "custom stuff" to a framebuffer and then drawing that with ImGui seems like the sensible approach. Perhaps I don't understand what you are trying to accomplish, though. |
The custom shader is not rendering draw lists and cannot render draw lists, because when the call to the custom UserCallback in the _impl-files occurs
cmd_list is always empty. Therefore, draw lists are always rendered by the draw list shader. The custom shader renders custom graphics, in my example above that is a simple triangle, but it could also be a game engine or some other graphics producing application logic. Maybe I overlooked somethink, but what is the UserCallback else made for? I think it is absolutely necessary for the whole Dear ImGui-concept to have those UserCallbacks or at least to somehow (enable to user to) ensure that the draw list shader does not break during custom shader operation. Currently however, which is the reason for this pull request, custom shader operations (e.g. user callbacks) cause side effects on the draw list shader, because the draw list shader state is not restored by making enough glVertexAttribPointer-calls resp. there is no function I can call to do so. Even if I did not use the UserCallback to do custom graphics, e.g. rendering graphics to a texture instead (I think that is what you proposed) a single call to glVertexAttribPointer would already break the draw list shader. |
I am not sure why you say, "cmd_list is always empty" probably you meant "pcmd is empty" in the sense that it has a zero vertex count. We're passing pcmd so you can access the Most people are happy with rendering their engine/contents into an offscreen buffer because it's more practical and then from the ImDrawList point of view it's just a regular 2D textured quad. Of course, you are totally right that you can save on bandwidth by rendering directly without an intermediate buffer, and we ought to allow that.
Not sure what you mean here, as I understand it FYI I have just merged in change related to an old issue (#1217) to create the VAO locally in the draw function instead of creating it in e.g. The problem with the PR are that:
ANYWAY, going toward a solution: Someone whispered an idea into my ear yesterday, which is to standardize callback special values:
And we can expend this list with specific ones on a per-state basis. |
First of all, sorry for my late reply. I double checked whether everything works as I expect it to work and indeed, it does. Those VAOs are really great & thank you a lot! |
I am reopening this because although the PR won’t be taken as is, the discussion below should lead us to standardize a set of callback defines to reset the gpu state. |
Maybe we should move it to a new issue, this pull request thing does not really allow reopening as far as I can see. |
Branch has been merged in now. |
Compare #984.
What this pull request changes: for the OpenGL3-examples, (sdl_opengl3_example, opengl3_example) glVertexAttribPointer is now called every time the draw lists are drawn and not only when the draw list shaders are compiled. This allows the user to use custom glVertexAttribPointer in a draw_callback callback specified in
ImGui::GetWindowDrawList()->AddCallback(draw_callback, NULL);
This e.g. allows to execute a user defined OpenGL-program per window and have draw lists be executed on top: in the figure below, the black triangle is drawn by a different program than the yellow line, which is drawn by the draw list program.