Closed AuroreDupont closed 8 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.
https://github.com/veandco/go-sdl2/issues/54 I have had issues even without 'go' routining.
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
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()
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.
Seconding the wish for a go-sdl2 example with goroutines. This issue isn't very obvious to beginners of go or sdl.
I would suggest here, that sdl.Init() calls runtime.LockOSThread() internally, so that users of SDL do not need to worry about this anymore.
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
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.
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?