[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

Re: [pygame] Python threads, pygame, and pyopengl



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