[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