veandco / go-sdl2

SDL2 binding for Go
https://godoc.org/github.com/veandco/go-sdl2
BSD 3-Clause "New" or "Revised" License
2.23k stars 225 forks source link

Example of go-sdl2 using go routines #75

Closed AuroreDupont closed 8 years ago

AuroreDupont commented 9 years ago

SDL2 has threading requirements. For instance, it would seem that the thread creating the main window needs also to be the same thread for manipulating the renderer and for pooling events.

Is it possible to use go routines with go-sdl2?

krux02 commented 9 years ago

Generally, this is not possible. The context is bound to the thread, and go likes to swap the underlying thread. This has to be explicitly disabled, or the system crashes. But you can use goroutines with anything that does not require the context. EG generating maps, loading textures from hard disc etc. But loading them from memory on the gpu has to be done in the main thread.

2014-12-11 1:16 GMT+01:00 AuroreDupont notifications@github.com:

SDL2 has threading requirements. For instance, it would seem that the thread creating the main window needs also to be the same thread for manipulating the renderer and for pooling events.

Is it possible to use go routines with go-sdl2?

— Reply to this email directly or view it on GitHub https://github.com/veandco/go-sdl2/issues/75.

EvanTheB commented 9 years ago

https://github.com/veandco/go-sdl2/issues/54 I have had issues even without 'go' routining.

AuroreDupont commented 9 years ago

Hi,

What do you mean by "explicitly" ? I created this example: https://gist.github.com/AuroreDupont/f3deb3a9f60cfa950db2 You'll see just the fact of having a different go routine not related to SDL results in the following seg fault:

SIGSEGV: segmentation violation PC=0x7fff8687120f signal arrived during cgo execution

runtime.cgocall(0x4003490, 0x43d6e58) homebrew/Cellar/go/1.2.1/libexec/src/pkg/runtime/cgocall.c:149 +0x11b fp=0x43d6e40 github.com/veandco/go-sdl2/sdl._Cfunc_SDL_RenderClear(0x5915640, 0xc21002a000) github.com/veandco/go-sdl2/sdl/_obj/_cgo_defun.c:2644 +0x31 fp=0x43d6e58 github.com/veandco/go-sdl2/sdl.(_Renderer).Clear(0x5915640, 0x40250ae, 0x41e3e18) github.com/veandco/go-sdl2/sdl/render.go:338 +0x27 fp=0x43d6e70 main.(_SDLWindow).draw(0xc210042020) sdl/sdl2.go:40 +0x5e fp=0x43d6f10 main.(*SDLWindow).Show(0xc210042020) sdl/sdl2.go:67 +0x27 fp=0x43d6f20 main.SDLMainLoop() sdl/sdl2.go:79 +0x52 fp=0x43d6f40 main.main() sdl/sdl2.go:94 +0x28 fp=0x43d6f48 runtime.main() homebrew/Cellar/go/1.2.1/libexec/src/pkg/runtime/proc.c:220 +0x11f fp=0x43d6fa0 runtime.goexit() homebrew/Cellar/go/1.2.1/libexec/src/pkg/runtime/proc.c:1394 fp=0x43d6fa8

goroutine 3 [sleep]: time.Sleep(0x3b9aca00) /private/tmp/go-2sK7/go/src/pkg/runtime/time.goc:31 +0x31 main.HelloWorld() sdl/sdl2.go:87 +0x26 created by main.main sdl/sdl2.go:93 +0x21

goroutine 4 [syscall]: runtime.goexit() homebrew/Cellar/go/1.2.1/libexec/src/pkg/runtime/proc.c:1394

rax 0x0 rbx 0x5915640 rcx 0x43d6e58 rdx 0x43d6df0 rdi 0x5915640 rsi 0x44097e0 rbp 0xb0186df0 rsp 0xb0186df0 r8 0xc210001120 r9 0x43d6df0 r10 0xfdc33d4b0545a r11 0x286 r12 0x20db70f3de2a5 r13 0x20e31feb7d848 r14 0x590a510 r15 0x4004ec0 rip 0x7fff8687120f rflags 0x10206 cs 0x2b fs 0x0 gs 0x0

krux02 commented 9 years ago

you can only call Draw commands on the same system Thread, where you did SDL_Init(); to make shure that go does not change the underlying thread at will, you have to use: runtime.LockOSThread()

AuroreDupont commented 9 years ago

Ok. Thank you very much. That is why I suggest in this issue to add an example of go-sdl2 using go routines, as an example of what you just said. The example could be drawing in a background loop while a foreground loop polls the events and displays what the background loop drew when it is ready or something like that. It is just a suggestion.

ghost commented 9 years ago

Seconding the wish for a go-sdl2 example with goroutines. This issue isn't very obvious to beginners of go or sdl.

krux02 commented 9 years ago

I would suggest here, that sdl.Init() calls runtime.LockOSThread() internally, so that users of SDL do not need to worry about this anymore.

charneykaye commented 8 years ago

Here's an example I made, of go-sdl2 working with a goroutine. However, I'm noticing that the performance of this program is extremely choppy. https://github.com/charneykaye/go-SDL-experiements/blob/master/stars_goroutine.go

aqiank commented 8 years ago

I've added a new render_goroutines example which uses a global channel (recent addition to go-sdl2) where you can put your thread-sensitive calls like SDL's render functions. It's called sdl.CallQueue for now but if you guys have suggestions, go ahead.

The example code looks something like this:

// Set a WaitGroup to wait until all pixels are drawn
var wg sync.WaitGroup

for y := 0; y < winHeight; y++ {
    for x := 0; x < winWidth; x++ {
        wg.Add(1) 

        go func(x, y int) {
            // Do some fake processing before rendering
            r := byte(rand.Int())
            g := byte(rand.Int())
            b := byte(rand.Int())

            // Call the render function in the 'render' thread synchronously
            sdl.CallQueue <- func() {
                renderer.SetDrawColor(r, g, b, 255)
                renderer.DrawPoint(x, y)
                wg.Done()
            }
        }(x, y)
    }
}

// Wait until all pixels are drawn
wg.Wait()

Let me know what you guys think.