[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
Re: [pygame] Python threads, pygame, and pyopengl
Thanks for the info. I think what I'm going to do is clean up my
OpenGL loading code, which right now contains probably double the
number of functions I need, and wrap every distinct operation in
locks. I'll unlock after every texture load, every display list
creation, etc. Hopefully after cleanup of redundant functions this
won't be too much work.
Then, I'll have my main drawing code request a lock and keep it until
after the display flip. That way, all the loading is forced to happen
during the calculation and input processing of my main loop. The
loading thread will have a lock on most of the time but give it up
pretty quickly when requested. And I won't have to individually wrap
my drawing code in locks because loading is low enough priority that
we can waste some time between drawing calls.
Hopefully I don't run in to the problems you had using textures, etc.
-Zack
On May 12, 2009, at 4:48 PM, Brian Fisher wrote:
In my opinion, you will be happier just using one thread for all the
OpenGL stuff, and never deviating from that.
However, if you wanna know more details... you are only supposed to
use one thread per GL context. The basic reason why is that when
using the same context, 2 threads may interleave various stateful
calls - like glGetError, or immediate mode calls, or popmatrix
pushmatrix stuff. So if 2 threads were working without
communicating, basically everything you are doing can get messed up
in every way possible depending on timing, making it a testing
nightmare. But even if you are careful and do locking and state
management and all that, because multiple threads using the same
context is not a very common use case it's poorly tested, you can
expect various drivers and implementations to behave poorly in
different ways as well (my xp machine for instance used to segfault
whenever I'd try to call functions to read pixels from textures from
a second thread created by the first thread because it would mess up
texture sizes, no matter what the first thread was doing at the time
of the call - while my current machine seems to be fine with that
call, but has problems with deleting textures from different threads)
If you wanted to try to pursue multiple contexts, I'm not sure if
you would still have driver support issues (again it's rarely used
therefore rarely tested). Also, I'm not aware of a way to tell
PyOpenGL which GL context you want to draw with, or how to make
multiple opengl contexts for PyOpenGL to use, but the pyOpenGL list
can probably help you with that.
On the bright side, I think every platform has a call for binding
the context to a thread, and I'm 99% sure that the thread bindings
to contexts sticks to the thread exactly the way you'd hope. (see
glXMakeCurrent, wglMakeCurrent or aglSetCurrentControl), and you
should be able to set up contexts to draw to the same window, no
problem (on Windows you need two HDC's to the same HWND to make 2 gl
contexts, but _is_ supposed to be officially supported...)
In terms of getting parallelization without breaking the one thread
per context rule or without multiple contexts, you could set up some
kind of "queue" of stuff to load into video memory that your from-
disk loader thread adds images into as it loads them, and then your
gl drawing thread can load them lazily at it's pace. That way you
still get the CPU/Memory with Disk parallelization which is almost
always the biggest paralellization benefit you can get.
On Tue, May 12, 2009 at 12:22 PM, Zack Schilling <zack.schilling@xxxxxxxxx
> wrote:
I want to dynamically load levels for my game in python. I use
OpenGL for drawing, mostly display lists. I want to spawn a low-
priority thread that can create a new level object and activate its
load method. The load method takes up to 5 seconds to run. It is
loading images with pygame, splitting them up, generating large
numpy arrays, binding textures, and building display lists. I know
that if I simply create a thread and tell it to go without any
modification, the OpenGL calls building the display lists in the
loading thread will overlap with normal display code and cause
strange, flickery drawing (not to mention ruining the level being
loaded).
What's the best option here? Can a thread lock block the main
program's execution? Because that's where the drawing code is. Is
there a way to set up PyOpenGL so that OpenGL knows to separate the
two different voices talking to it (but still throw everything into
the same context)?
This game is a fun project for me, but I also expect to plow my way
though some advanced programming techniques, so don't hold back
suggestions for the sake of complexity.
Thanks,
Zack