yt-project / yt_idv

Interactive volume rendering for yt
Other
8 stars 6 forks source link

OpenGL context error on Ubuntu 22.04.2 in wayland session #81

Open chrishavlin opened 1 year ago

chrishavlin commented 1 year ago

Edit (Summary)

Summarizing this thread: recent versions of Ubuntu have switched to using the Wayland graphics protocol by default (from Xorg). At present, pyglet does not support Wayland. While using pyglet on its own still works (thanks to xWayland), using pyimgui-pyglet results in PyOpenGL selecting the incorrect graphics backend. Forcing PyOpenGL to use Xorg solves this ($ export PYOPENGL_PLATFORM='glx'). Alternatively, you can select an Xorg session on the Ubuntu login screen.

Original:

Just created a new yt_idv environment with python 3.9.16 on ubuntu 22.04.2, installed everything and got the following error trying to run examples/amr_volume_rendering.py:

Traceback (most recent call last):
  File "/home/chavlin/src/yt_general/yt_idv/examples/amr_volume_rendering.py", line 7, in <module>
    rc = yt_idv.render_context(height=800, width=800, gui=True)
  File "/home/chavlin/src/yt_general/yt_idv/yt_idv/rendering_contexts/__init__.py", line 22, in render_context
    return PygletRenderingContext(**kwargs)
  File "/home/chavlin/src/yt_general/yt_idv/yt_idv/rendering_contexts/pyglet_context.py", line 61, in __init__
    gui = SimpleGUI(self)
  File "/home/chavlin/src/yt_general/yt_idv/yt_idv/simple_gui.py", line 20, in __init__
    self.renderer = create_renderer(window)
  File "/home/chavlin/.pyenv/versions/yt_idv/lib/python3.9/site-packages/imgui/integrations/pyglet.py", line 245, in create_renderer
    return PygletProgrammablePipelineRenderer(window, attach_callbacks)
  File "/home/chavlin/.pyenv/versions/yt_idv/lib/python3.9/site-packages/imgui/integrations/pyglet.py", line 213, in __init__
    super(PygletProgrammablePipelineRenderer, self).__init__()
  File "/home/chavlin/.pyenv/versions/yt_idv/lib/python3.9/site-packages/imgui/integrations/pyglet.py", line 55, in __init__
    super(PygletMixin, self).__init__()
  File "/home/chavlin/.pyenv/versions/yt_idv/lib/python3.9/site-packages/imgui/integrations/opengl.py", line 60, in __init__
    super(ProgrammablePipelineRenderer, self).__init__()
  File "/home/chavlin/.pyenv/versions/yt_idv/lib/python3.9/site-packages/imgui/integrations/base.py", line 17, in __init__
    self._create_device_objects()
  File "/home/chavlin/.pyenv/versions/yt_idv/lib/python3.9/site-packages/imgui/integrations/opengl.py", line 125, in _create_device_objects
    gl.glVertexAttribPointer(self._attrib_location_position, 2, gl.GL_FLOAT, gl.GL_FALSE, imgui.VERTEX_SIZE, ctypes.c_void_p(imgui.VERTEX_BUFFER_POS_OFFSET))
  File "/home/chavlin/.pyenv/versions/yt_idv/lib/python3.9/site-packages/OpenGL/latebind.py", line 63, in __call__
    return self.wrapperFunction( self.baseFunction, *args, **named )
  File "/home/chavlin/.pyenv/versions/yt_idv/lib/python3.9/site-packages/OpenGL/GL/VERSION/GL_2_0.py", line 469, in glVertexAttribPointer
    contextdata.setValue( key, array )
  File "/home/chavlin/.pyenv/versions/yt_idv/lib/python3.9/site-packages/OpenGL/contextdata.py", line 58, in setValue
    context = getContext( context )
  File "/home/chavlin/.pyenv/versions/yt_idv/lib/python3.9/site-packages/OpenGL/contextdata.py", line 40, in getContext
    raise error.Error(
OpenGL.error.Error: Attempt to retrieve context when no valid context

I noticed that our test requirements pin PyOpenGL to 3.1.5, so I downgraded and that fixed the error. Should we be pinning PyOpenGL in setup.cfg? It currently specifies pyOpenGL>=3.1.5. Note that I first downgraded from 3.1.7 to 3.1.6 and still got the error before downgrading again to 3.1.5.

matthewturk commented 1 year ago

Whoa, this is not great! I don't know why the new version wouldn't work.

chrishavlin commented 1 year ago

Figured it out! It is actually an ubuntu issue: after upgrading to 22, ubuntu was using Wayland by default. After switching back to Xorg, I can use the latest PyOpenGL without error.

Some useful issues for context over on pygame: https://github.com/pygame/pygame/issues/3110 https://github.com/pygame/pygame/issues/3114

It's interesting that it works at all with PyOpenGL==3.1.5. Might indicate a bug in PyOpenGL? Or that I need to setup my environment a little more carefully? I'll keep digging but I'd say this is a little less critical than it appeared at first.

matthewturk commented 1 year ago

This only makes me feel worse about it! :smile: I hope we can figure out how to address this, as Linux is usually one of the more reliable deployment environments for OpenGL stuff lately, if I am remembering correctly.

chrishavlin commented 1 year ago

well it seems pyopengl has had some trouble in detecting Wayland vs Xorg in the past (https://sourceforge.net/p/pyopengl/mailman/message/36989497/): Wayland needs to use egl. I'll see if adjusting some environment variables helps...

chrishavlin commented 1 year ago

OK, so I think I've narrowed this down a bit. pyglet on it's own is OK on wayland (cause it'll use the xwayland forwarding/wrapping even though it doesnt have native wayland support). The problem is coming in the imgui-pyglet integration. imgui's example, https://github.com/pyimgui/pyimgui/blob/master/doc/examples/integrations_pyglet.py , crashes with the same error message above when I'm logged into a wayland session AND have PyOpenGL > 3.1.5. Pinning PyOpenGL to 3.1.5 on wayland OR using an xorg session (with any version of PyOpenGL) works. So I think this is enough to ask upstream in pyimgui.

chrishavlin commented 1 year ago

An issue already exists! https://github.com/pyimgui/pyimgui/issues/318 the second comment notes that it also errors for pyglet.

chrishavlin commented 1 year ago

Ok, found a potential fix: explicitly telling PyOpenGL what to use seems to work. After setting the following environment variable

$ export PYOPENGL_PLATFORM='glx'

I can run our examples in a Wayland session with the latest PyOpenGL.

@matthewturk , I think I'll just add a note to the installation instructions recommending to either set this environment variable or run yt_idv in an xorg session. We could also try setting the environemnt variable on initial import of yt_idv via os.environ but relying on import order not be the most stable...

matthewturk commented 1 year ago

hmm. Can you take a look at what is going wrong with yt_idv/rendering_contexts/__init__.py?

chrishavlin commented 1 year ago

well I don't think anything is going wrong with yt_idv's selection. We still want the pyglet default.

What I think is happening: pyglet doesnt support wayland (yet?) and when I run a standalone pyglet app, it somehow tells PyOpenGL to use glx, not wayland without me having to set any environment variables. But for some reason when running pyimgui-pyglet, pyglet still needs glx, but PyOpenGL thinks it's OK to use a different session type and I need to set this environment variable to enforce that.