Thread: [PyOpenGL-Users] expected performance vs pyglet
Brought to you by:
mcfletch
From: Jonathan H. <ta...@ta...> - 2010-11-19 01:14:47
|
Hey folks. I'm finding pyglet's OpenGL bindings give me at least 2 times faster framerates than PyOpenGL's. This ratio is surprisingly high to me, am I right to be surprised? I'm probably doing lots wrong - I don't really know what I'm doing. Here's what I've checked. What else should I be thinking about? I'm setting ERROR_CHECKING=False If I run with FULL_LOGGING then I see no extra GL calls to retrieve status values. I tried running with ERROR_ON_COPY=True, no errors are reported I'm running Python with -O. I have OpenGL-accelerate installed, although I have done nothing to 'enable' it or explicitly use it. Do I need to? I'm drawing 500 cubes, each with a separate glDrawElements call, using: for item in items: gl.glPushMatrix() gl.glMultMatrixf(item.matrix) gl.glVertexPointer( Glyph.DIMENSIONS, gl.GL_FLOAT, 0, item.glyph.glvertices # ctypes array of GLfloats ) gl.glDrawElements( gl.GL_TRIANGLES, len(item.glyph.glindices), gl.GLushort, item.glyph.glindices # ctypes array GLushorts ) gl.glPopMatrix() (There are also color and normal array pointers defined outside the loop - they never change.) Where I'm defining 'gl' using: if use_pyglet_bindings: from pyglet.gl import gl from pyglet.gl import glu else: import OpenGL OpenGL.ERROR_CHECKING = __debug__ OpenGL.ERROR_ON_COPY = __debug__ OpenGL.ERROR_LOGGING = False OpenGL.FULL_LOGGING = False from OpenGL import GL as gl from OpenGL import GLU as glu (obviously some function signatures aren't quite the same in pyglet and PyOpenGL, so I'm working around those where I have to. In particular, the definition of item.matrix passed to glMultMatrixf changes depending on which GL bindings I use, effectively: if use_pyglet_bindings: matrix = Matrix4() # pyeuclid, pure python if item.position is not None: matrix.translate(*item.position) if item.orientation is not None: matrix *= item.orientation.get_matrix() item.matrix = matrix_to_ctypes(matrix) else: matrix = item.orientation.get_matrix() # pure python matrix[12:15] = item.position item.matrix = numpy.array(matrix[:], dtype=GL.GLfloat) (this code is only run once for each item on startup - for the moment, until I figure this out, my items never move or rotate, so the initial matrix on each item remains constant) I'm on WindowsXP, Python2.7, PyOpenGL3.0.1, with OpenGL2.1 ATI drivers. (the most recent drivers available for my hardware, on both a laptop and a desktop.) -- Jonathan Hartley Made of meat. http://tartley.com ta...@ta... +44 7737 062 225 twitter/skype: tartley |
From: Mike C. F. <mcf...@vr...> - 2010-11-29 19:02:47
|
On 10-11-18 08:14 PM, Jonathan Hartley wrote: > Hey folks. > > I'm finding pyglet's OpenGL bindings give me at least 2 times faster > framerates than PyOpenGL's. This ratio is surprisingly high to me, am I > right to be surprised? > I'd probably expect around 1.5x at least, and 2x doesn't surprise *me* :) . Pyglet doesn't, AFAIK do any pointer-reference interception, so their ctypes calls are direct-to-C, while PyOpenGL is doing a *lot* of Python code for every array-handling call. Even when that code is translated to Cython, it is still a lot of machinery involved compared to passing a ctypes pointer for everything. > I'm probably doing lots wrong - I don't really know what I'm doing. > Here's what I've checked. What else should I be thinking about? > > I'm setting ERROR_CHECKING=False > If I run with FULL_LOGGING then I see no extra GL calls to retrieve > status values. > I tried running with ERROR_ON_COPY=True, no errors are reported > I'm running Python with -O. > ERROR_CHECKING = False CONTEXT_CHECKING = False STORE_POINTERS = False FULL_LOGGING = False ALLOW_NUMPY_SCALARS = False would be the settings to disable as much of the machinery as possible, but even with that, we're still doing more code than Pyglet for each array call. I'd still expect around 1.5x run-time for PyOpenGL vs. Pyglet on the kind of code you're writing (lots of calls, a "classic" OpenGL approach). To get real performance improvements, vertices into a single numpy array, put your matrices into another array, multiply matrices * vertices and draw with a single call from an index array across a VBO. If you're updating matrices on each call, use a shader and do the multiply on the video-card (with a streaming VBO for the matrices and a static one for the points). The overhead of pointer calls gets amortized as you get larger and larger arrays in PyOpenGL, so it tends to favour the modern VBO + shader model rather than the older classic OpenGL model. HTH, Mike -- ________________________________________________ Mike C. Fletcher Designer, VR Plumber, Coder http://www.vrplumber.com http://blog.vrplumber.com |