Re: Python - Pyglet - .draw() objects in two different Threads

846 views
Skip to first unread message

Winston Wolff

unread,
Feb 4, 2013, 7:14:20 PM2/4/13
to pyglet...@googlegroups.com
I haven't used threads with Pyglet, but other GUI toolkits also restrict changing gui stuff from other threads. I usually fix this by having having the worker threads tell the "gui thread" something more symbolic like "I'm working on file X" and then the gui thread takes that message and changes the label text.

-Winston

On Feb 4, 2013, at 3:15 PM, Lord Anton Hvornum <anton...@gmail.com> wrote:

> I have a scenario where:
>
> class main(pyglet.window):
> ...
> generates a lot of objects
>
> sends a label to another thread
>
> class the_thread(Thread):
> ...
> tries to:
> self.lable.text = 'New string'
> self.lable.draw()
>
> Which causes:
>
> > GLException: invalid operation
>
>
> Even keeping the .draw() part in the main thread and just update the text causes the error.
> Using the "lock" function via self.lable.being_update() and then calling .end_update() causes the error.
>
> The code i've got works fine if i take away the Threading part, which, i don't because the whole idea with the thread is to have a socket and some processing operations being performed at X times / minute under different circumstances.
>
>
> Any idea if it's possible to solve at all?
> Can i hook the thread objects to the main window resorce somehow or blit it into the main instance? I **think** i've solved this once back in the days when i was programming at a helpdesk by blitting the object into a "scene" or something but i can't find my code, and it might not even have been based on Pyglet to begin with.
>
> --
> You received this message because you are subscribed to the Google Groups "pyglet-users" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to pyglet-users...@googlegroups.com.
> To post to this group, send email to pyglet...@googlegroups.com.
> Visit this group at http://groups.google.com/group/pyglet-users?hl=en.
> For more options, visit https://groups.google.com/groups/opt_out.
>
>

Tristam MacDonald

unread,
Feb 4, 2013, 7:23:00 PM2/4/13
to pyglet-users
On Mon, Feb 4, 2013 at 6:15 PM, Lord Anton Hvornum <anton...@gmail.com> wrote:
I have a scenario where:

    class main(pyglet.window):
       ...
       generates a lot of objects
    
       sends a label to another thread
    
    class the_thread(Thread):
       ...
       tries to:
           self.lable.text = 'New string'
           self.lable.draw()

Which causes:

> GLException: invalid operation


Even keeping the .draw() part in the main thread and just update the text causes the error.
Using the "lock" function via  self.lable.being_update() and then calling .end_update() causes the error.

The code i've got works fine if i take away the Threading part, which, i don't because the whole idea with the thread is to have a socket and some processing operations being performed at X times / minute under different circumstances.


Any idea if it's possible to solve at all?
Can i hook the thread objects to the main window resorce somehow or blit it into the main instance? I **think** i've solved this once back in the days when i was programming at a helpdesk by blitting the object into a "scene" or something but i can't find my code, and it might not even have been based on Pyglet to begin with.

In general, OpenGL is not compatible with multi-threading. 

In general, Python is not compatible with multi-threading either.

--
Tristam MacDonald
Software Development Engineer, Amazon.com

Peter Enerccio

unread,
Feb 5, 2013, 1:40:52 AM2/5/13
to pyglet...@googlegroups.com
Except that python is compatible with multi threading. It just make it single threading practically.
As for the opengl, have you tried making sharing context? I am not sure if drawing objects is allowed in other threads,
but if it is, it must be done with shared context.


2013/2/5 Tristam MacDonald <swift...@gmail.com>

--
You received this message because you are subscribed to the Google Groups "pyglet-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pyglet-users...@googlegroups.com.
To post to this group, send email to pyglet...@googlegroups.com.
Visit this group at http://groups.google.com/group/pyglet-users?hl=en.
For more options, visit https://groups.google.com/groups/opt_out.
 
 



--
Bc. Peter Vaňušanik
http://www.bishojo.tk

Tristam MacDonald

unread,
Feb 5, 2013, 10:31:48 AM2/5/13
to pyglet-users
On Tue, Feb 5, 2013 at 1:40 AM, Peter Enerccio <ener...@gmail.com> wrote:
Except that python is compatible with multi threading. It just make it single threading practically.

Thus the point of my comment: since you don't get any real benefit from multi-threading, you might as well use fibers/tasklets/greenlets, which won't intrude race conditions, won't break OpenGL, and won't degrade performance either.
 
As for the opengl, have you tried making sharing context? I am not sure if drawing objects is allowed in other threads,
but if it is, it must be done with shared context.

That will generally work, but because of Python's GIL, you won't get any benefits...

Tristam MacDonald

unread,
Feb 15, 2013, 5:14:05 PM2/15/13
to pyglet-users
On Fri, Feb 15, 2013 at 10:36 AM, Lord Anton Hvornum <anton...@gmail.com> wrote:
As for *GL applications not being able to render things in different threads, i'm aware of the fact that this is normally how it's done because it will cause major graphical errors if updated in the wrong time etc, but technically it's possible so there for, it should be doable :)

It is certainly possible to render things on different threads, but only one thread at a time may render into a single context.


--

To make your original example work, you need to call pyglet.gl.Context.set_current() to make the context active each time you switch threads, which means that you need to wrap each OpenGL drawing operation (and by extension, pretty much all of pyglet's functionality) with a mutex, to prevent both threads from attempting to access them at the same time.

At this point you will indeed be rendering in two threads, but only one of them at a time, so you don't buy any performance this way (you could just as well perform non-OpenGL work on the secondary thread, and post the results back to the main thread for rendering). And between the overhead of context switches, mutexes and set_current(), you'll may well be sacrificing performance.

--

You can also, as Peter says, create a second context that shares resources with your main context. This will allow you to load textures, display lists, buffers and shaders in one context, and then use them from the other. But you can't actually render from both contexts - only the primary one is connected to the display surface.

This method used to often be used to load large textures into the GPU asynchronously, but it has pretty much been superseded by using a PBO to make the initial transfer to the GPU.
Reply all
Reply to author
Forward
0 new messages