mmatl / pyrender

Easy-to-use glTF 2.0-compliant OpenGL renderer for visualization of 3D scenes.
http://pyrender.readthedocs.io/
MIT License
1.31k stars 225 forks source link

'invalid operation' error on Windows with WGL #169

Closed cosw0t closed 3 years ago

cosw0t commented 3 years ago

Hi,

I'm facing a new kind of error after the merge of #167

these lines are to blame:

https://github.com/monsieurgustav/pyrender/blob/10ada1d4f895a4e9272299347def675ec4ba4407/pyrender/platforms/pyglet_platform.py#L57-L58

And the error is:

  File "C:\tools\miniconda3\envs\sim_datacollection\lib\site-packages\pyrender\offscreen.py", line 102, in render
    retval = self._renderer.render(scene, flags, seg_node_map)
  File "C:\tools\miniconda3\envs\sim_datacollection\lib\site-packages\pyrender\renderer.py", line 141, in render
    self._shadow_mapping_pass(scene, ln, flags)
  File "C:\tools\miniconda3\envs\sim_datacollection\lib\site-packages\pyrender\renderer.py", line 412, in _shadow_mapping_pass
    self._configure_shadow_mapping_viewport(light, flags)
  File "C:\tools\miniconda3\envs\sim_datacollection\lib\site-packages\pyrender\renderer.py", line 1025, in _configure_shadow_mapping_viewport
    glBindFramebuffer(GL_FRAMEBUFFER, self._shadow_fb)
  File "C:\tools\miniconda3\envs\sim_datacollection\lib\site-packages\OpenGL\error.py", line 232, in glCheckError
    baseOperation = baseOperation,
OpenGL.error.GLError: GLError(
    err = 1282,
    description = b'invalid operation',
    baseOperation = glBindFramebuffer,
    cArguments = (GL_FRAMEBUFFER, 1)
)

Process finished with exit code 1

Interestingly enough, this happens the 2nd time i call the offscreen renderer, whereas the first time it renders correctly. Which means that the wglMakeCurrent call is misplaced.

Any ideas what went wrong when starting to use WGL?

cosw0t commented 3 years ago

@monsieurgustav any ideas? does this work for you?

monsieurgustav commented 3 years ago

I got the same issue this morning... I created the PR when using pyrender on another project. It renders a single image so it was working then.

TBH, I'm not familiar at all with pyrender. The PR is just the same code for WGL than it is for GLX. It seems like self._window.switch_to() does not what we expect.

monsieurgustav commented 3 years ago

More generally, I don't think a renderer should call make_current/make_uncurrent every frame.

cosw0t commented 3 years ago

Yes, single image works fine because make_uncurrent is called after the frame is rendered. The error would occur on the second pass so you wouldn't see it.

Why did you need to wglMakeCurrent(self._window.canvas.hdc, None). Did it show any benefits?

Can we figure out if a make_uncurrent is actually needed and what it should do? It seems to me that pyglet handles internally the make_current and switch_to with specialized classes for win32, xlib etc, but it has no make_uncurrent so i was wandering if anybody knows why it's needed in the first place? @mmatl ?

cosw0t commented 3 years ago

it was introduced in https://github.com/mmatl/pyrender/commit/db1f6fd7bf48209cbd8b6c4b84e0856314b822c0 seemingly for multithreading access.

monsieurgustav commented 3 years ago

I didn't need this call to wglMakeCurrent. (again, it's just reflecting the GLX variant) The main point was to remove a 'GLX not found' exception on Windows.

The only reason I ever found make a context not current anymore was in a multi-thread environment (a context cannot be current in several threads at a time)

cosw0t commented 3 years ago

This can be solved with the try/except block. Any objections to reverting your commit https://github.com/mmatl/pyrender/commit/a1b46160cc411149c81d391adeea5c2e085d96ad?

monsieurgustav commented 3 years ago

No objection if you add the try/except instead, I let you do it though.

mmatl commented 3 years ago

Hi All,

Sorry, didn't have a windows PC to test this on. I merged and deployed a new version.