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

Re: [pygame] Cheap COW clones for surfaces



The mutatation would be on the logic thread side. Consider this:

draw_to_screen(surf_a,  ...)
if cond:
    surf_a.blit(surf_b, ...)
draw_to_screen(surf_a, ...)

Currently draw_to_screen() is synchronous. I'd like it to queue the blit instead, to happen in another thread. If I just did

def draw_to_screen(surf, ...):
    draw_queue.put((surf, ...))

then there's a race condition - surf_a may be drawn twice with the surf_b update.

If draw_to_screen() is implemented like

def draw_to_screen(surf, ...):
     draw_queue.put((surf.copy(), ...))

Then I get no change in behaviour, but I copy on every blit, on the logic thread, ie 2 copies per frame regardless of whether cond is True.

Changing the implementation of copy to create a COW clone means that the buffer copy actually happens at this line, if it is hit:

surf_a.blit(surf_b, ...)

Which means that there's 1 copy if cond is True and 0 if cond is False.

On Sun, 17 Jun 2018, 20:59 Radomir Dopieralski, <pygame@xxxxxxxxxxxx> wrote:
On Sun, 17 Jun 2018 17:48:26 +0200
Daniel Pope <mauve@xxxxxxxxxxxxxx> wrote:

> I have been thinking for some time about how to optimise Pygame Zero
> games on Raspberry Pi. Most Pi models have multiple cores and an
> obvious improvement is to parallelise. Logic has to be synchronous
> but I would like to offload painting the screen to a separate thread.
>
> The problem I would have is in passing references to mutable objects
> between threads. Primarily this applies to Surface objects, which are
> mutable and expensive to copy. If I have a draw thread that maintains
> a queue of screen blit operations, I want the queue to hold
> references to surface data that won't change even if I later mutate
> the surfaces in the logic thread.

Sorry if I am missing something obvious, but it seems to me that the
draw thread doesn't need to mutate the surfaces? I mean, it only
accesses them in a read-only fashion to render them. So you don't need
to pass references to mutable objects — the drawing thread can get a
read-only reference. Why do you need it to have a reference to
non-changing data? After all, if it changes, you will have to re-draw
it in the next frame anyways. Unless the drawing thread is more than
one frame behind (which really shouldn't happen), you don't care about
the data changing.

--
Radomir Dopieralski