Re: [PyOpenGL-Users] PyOpenGL Release 3.0.0 (final)
Brought to you by:
mcfletch
|
From: Mike C. F. <mcf...@vr...> - 2009-04-02 15:12:05
|
Lorenzo Mancini wrote:
> Hello Mike, this really is great news! Congratulations!
>
>
>> You should expect a performance decline with the use of PyOpenGL 3.x
>> versus PyOpenGL 2.x! PyOpenGL 3.x will have an accelerator module
>> released in time to provide better performance, but the development
>> method (ctypes) is inherently slower than the C (SWIG) method
>> previously used.
>
> In the past days I've tried OpenGL_accelerate on some code of mine
> that suffers an expected 50% performance loss switching from pyopengl
> 2.x to 3.x, and it already yields a little speedup; since you are
> speaking in future tense, does this mean that more consistent
> improvements on OpenGL_accelerate are planned?
>
> [[Note: the code I'm talking about is heavily display-lists and other
> OpenGL legaciness based, so probably it doesn't represent a valid test
> bench for pyopengl 3.x performance measurements.]]
I'm intending to get rather more (Cython) accelerator helpers in
OpenGL_accelerate, but no, it likely won't be focusing on the legacy
APIs. Basically I'm planning to focus on the array-handling APIs so
that we can reduce the overhead there to something reasonable. There
are a considerable number of performance improvements still lying on the
ground in the wrapper mechanism that could be fairly straightforwardly
fixed if I can find the time. I also want to look into whether we can
simplify some of the wrapper operations if you enable legacy-free behavior.
>
>> Also consider using the package-level configuration flags to remove
>> "support" functionality as you near release, use of these flags can
>> provide more than 2x speedup in most cases.
>
> Are you talking about OpenGL.FORWARD_COMPATIBLE_ONLY? To do that, the
> OpenGL code in the application must be legacy-free, correct?
Nope, FORWARD_COMPATIBLE_ONLY is part of the migration path machinery
(which is another of the areas I'm intending to focus on), it doesn't
give you any performance improvements, it just disables the old APIs and
lets you know which pieces are legacy by raising errors (though it
doesn't do this for GLUT/GLU). Code that is entirely forward compatible
(legacy free) is going to be reasonably fast, because it *must* use VBOs
and shaders and there's basically nothing going on within the Python
code[1]. I'll be looking at optimizing those paths fairly heavily as
well, as that's where we need to go. However, the flag itself doesn't
make your code any faster, it just disables the legacy stuff so you
can't use it.
The flags that impact performance are:
* ERROR_CHECKING -- huge performance win, but no error checking, use
at the end of the dev cycle when you know your code is handling
all cases properly and want a performance boost, often close to 2x
improvement, as it halves the number of OpenGL calls in many cases.
* ERROR_LOGGING -- less of a performance win, but removes a single
wrapper call from every OpenGL call, if you turn off error
checking then this is turned off as well, but you can disable just
this to remove the function-call overhead
* ERROR_ON_COPY -- if set, will tell you when you are passing
incompatible arrays to array-handling functions (thus requiring a
copy of the array). For large array-oriented code-bases array
copying can become a huge bottleneck, so you can set this flag to
True to be warned of the problem. By default it silently fixes
the problem at the cost of performance. Eventually this will
likely *also* reject list/tuple types as array values, as they
require a data-copy as well.
* ALLOW_NUMPY_SCALARS -- if set, works around a bug in older
Python's ctypes that disallowed use of numpy scalars as return
values, has a large negative performance penalty, so is currently
disabled by default
The new one I plan to introduce will likely have this effect:
* disable pointer-storage-for-safety behavior, currently PyOpenGL
stores the pointer objects you pass it in order to prevent
memory-access failures, this behavior becomes unnecessary when we
have full ERROR_ON_COPY behavior and you've fixed all of your code
to pass in objects which are compatible by default. The behavior
is also unneeded with legacy-free arrays, as data-copying happens
during the call in *all* cases, so there's no need for the GL to
access the data "later".
The idea being that by default the system will be as robust and friendly
as possible, but as you move your application toward release you'll
start peeling off the layers of "nets" to improve your performance.
>> Since the release of PyOpenGL 2.x another common OpenGL binding for
>> Python has become popular and may be an appropriate choice for your
>> projects. The Pyglet project (http://www.pyglet.org) has a full
>> OpenGL binding in "raw" C style, along with many higher-level
>> utilities to aid in the development of games, all of which can be
>> easily installed on common platforms.
>
> As I wrote in a previous message, such a "raw" C style wrapper is also
> hidden in PyOpenGL, you just have to import from OpenGL.raw.GL instead
> of OpenGL.GL, and switch OpenGL.ERROR_CHECKING to False.
There's a few more differences (PyOpenGL's wrapper does more to each
function in order to be as friendly and safe as possible), but yes, that
is the basic idea of the "raw" hierarchy.
> This can improve performance (I get a 100% speedup with the codebase
> mentioned above) and bring it to the levels of 2.x, at the cost of
> some ctypes pollution in the code - raw wrappers of pyopengl and
> pyglet are almost indistinguishable both performance and code
> appearance wise.
You should still see a performance win on Pyglet unless you're using
OpenGL_accelerate. It does far less per-call than PyOpenGL in most cases.
> Talking about pyglet, some time ago I happened to read their automatic
> wrapper generator: I found it nice and easily pluggable in a toy
> project of mine. Since it uses the same ctypes technology and I
> remember you praising it yourself in a past presentation of yours, are
> you planning to merge it into pyopengl3.x to avoid duplicating efforts?
Yup, my intention is to use Pyglet's generator to replace the PyOpenGL
generation mechanism. That was put on hold to focus on just getting the
library out the door. The proof of concept was able to generate
basically the same wrapper as PyOpenGL for the core, but there were some
subtle differences from the current raw wrappers that wound up making
the result unstable in my testing. That should all just be a matter of
time to fix... unfortunately, time is something I seem to have little of
these days :) .
Enjoy,
Mike
[1] The one big anti-pattern for legacy-free is the individual-quad
rendering pattern that a lot of people are using in current PyOpenGL.
You (including me) really need to switch to texture atlases for things
like rendering text/sprites and use a big buffer with a shader that
renders the sprites with a single pass.
--
________________________________________________
Mike C. Fletcher
Designer, VR Plumber, Coder
http://www.vrplumber.com
http://blog.vrplumber.com
|