haskell-opengl / OpenGL

Haskell bindings to OpenGL
http://www.haskell.org/haskellwiki/OpenGL
BSD 3-Clause "New" or "Revised" License
147 stars 26 forks source link

glEnd called twice by renderPrimitive (on Windows) #87

Open trbauer opened 6 years ago

trbauer commented 6 years ago

The following minimal program calls glEnd twice within renderPrimitive. This is on Windows 32b package version OpenGL 3.0.0.2.

import Graphics.UI.GLUT

main :: IO ()
main = do
  (_progName, _args) <- getArgsAndInitialize
  _window <- createWindow "Hello World"
  displayCallback $= display
  mainLoop

display :: DisplayCallback
display = do
  let vertex3f x y z = vertex (Vertex3 x y (z :: Float))
  clear [ ColorBuffer ]
  renderPrimitive Points $ do
    vertex3f 0 0 0
    putStrLn "rendering point"
    get errors >>= print -- no error
  putStrLn "after renderPrimitive" -- error here
  get errors >>= print
  flush

I've reproduced with GHC 8.0.1 and GHC 8.0.2. This pollutes the error state for programs. OpenGL 2.9.0.2 on a Mac with GHC 7.8.3 does not exhibit the problem.

svenpanne commented 6 years ago

I suspect that you have a problem with picking the right OpenGL context. This depends quite a bit on your platform/driver. There are a few things to consider here:

initialContextFlags $= [ DebugContext ]
debugMessageCallback $=
  Just (\(DebugMessage _source _typ _ident _severity message) -> putStrLn message)
debugOutputSynchronous $= Enabled

I've tried your program (without the incorrect get errors) under Linux and Mesa 17.07. It works fine if I use a compatibility context and complains as expected when I use a forward-compatible context. I can try this later on a Windows box, but I suspect that the result will stay the same.

svenpanne commented 6 years ago

After some research and epic debugging sessions, it seems that on Windows we are a victim of the problem described in https://cgit.freedesktop.org/mesa/mesa/commit/?id=c7f0755caa1c39d5433e37c53242ef251aa4fc3a:

... The basic problem is Microsoft's opengl32.dll calls glFlush from wglGetProcAddress() ...

:scream: Just like in the test mentioned in the commit above, a glFlush is implicty happening while a glBegin/glEnd pair is open, which is an OpenGL error. Using OpenGL's debug API introduced in 4.3 one gets the following information:

source: SOURCE_API
type: TYPE_ERROR
id: 1282
severity: SEVERITY_HIGH
message (length 136): GL_INVALID_OPERATION error generated. Calling glFlush from the current immediate mode state is invalid. Check glBegin() / glEnd() pairs.

The good thing: This explains why this is a Windows-only problem. The bad thing: Without totally changing the way OpenGLRaw accesses OpenGL entry points, I see no way around that problem. I need to think about this and look at other dynamic OpenGL loaders. One sledgehammer would be: Load all entry points at once (but still lazily, so we have the right context), which might be a big performance hit during startup.

Thanks for a great bug report, it's a miracle why this was not reported earlier.

trbauer commented 6 years ago

You're awesome Sven!!! Thanks for following up. For my part, I can work around it in my program. I love Haskell and I love the OpenGL package you guys maintain and love how simple and clear the tutorial is.

You rock!

On Mon, Sep 4, 2017 at 12:20 PM, Sven Panne notifications@github.com wrote:

After some research and epic debugging sessions, it seems that on Windows we are a victim of the problem described in https://cgit.freedesktop.org/ mesa/mesa/commit/?id=c7f0755caa1c39d5433e37c53242ef251aa4fc3a:

... The basic problem is Microsoft's opengl32.dll calls glFlush from wglGetProcAddress() ...

😱 Just like in the test mentioned in the commit above, a glFlush is implicty happening while a glBegin/glEnd pair is open, which is an OpenGL error. Using OpenGL's debug API introduced in 4.3 one gets the following information:

source: SOURCE_API type: TYPE_ERROR id: 1282 severity: SEVERITY_HIGH message (length 136): GL_INVALID_OPERATION error generated. Calling glFlush from the current immediate mode state is invalid. Check glBegin() / glEnd() pairs.

The good thing: This explains why this is a Windows-only problem. The bad thing: Without totally changing the way OpenGLRaw accesses OpenGL entry points, I see no way around that problem. I need to think about this and look at other dynamic OpenGL loaders. One sledgehammer would be: Load all entry points at once (but still lazily, so we have the right context), which might be a big performance hit during startup.

Thanks for a great bug report, it's a miracle why this was not reported earlier.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/haskell-opengl/OpenGL/issues/87#issuecomment-327017658, or mute the thread https://github.com/notifications/unsubscribe-auth/ABskgAqvDsW0FH0VxWwqP6mj9Rob8Fktks5sfE17gaJpZM4PCJzm .