Can I use sdl in a new thread not the main thread?Is there any one help me?
You can. But you need to ensure that you’re calling SDL_PumpEvents in same thread as SDL_Init. Please note that SDL_PumpEvents is implicitly called by SDL_PollEvent. Also there can be issue with rendering via SDL - because that subsystem expecting that it’s update in on main thread.
See remarks section at SDL_PumpEvents - SDL Wiki
You can try, but it’s not really built for it.
If you’re sure you want to try it, first get it to work in your main thread, then move it over and run copious amounts of testing. If you still have problems, you might be able to alleviate them by making sure you don’t have certain SDL functions operating at the same time as certain other things. If that doesn’t fix it, you’re on your own.
I actually load textures in a separate thread from where I draw them, so that much at least can be done, but it took some mutex work to keep it from crashing unpredictably. I’ve tried it with a few other things but haven’t been able to get any of them to work reliably.
What backend? In my experience that can work using Direct3D, but not when using OpenGL. It’s safe to use surfaces that way, though.
I think it’s best to avoid this if at all possible.
The better model is to let the main thread handle the window(s) and the input events (or at least call SDL_PumpEvents() there) and do whatever else you were thinking about doing in the main thread in another thread.
Otherwise you might get into trouble on different operating systems or even just different graphics drivers. And it might not even be “works vs doesn’t work at all” but it could also be just instability or weird bugs.
For example, a fork of the dhewm3 Doom3 port, d3es-multithread, put rendering in a different thread (like id Software themselves planned for Doom3 originally, and then gave up because it didn’t work reliably - see this interview, search for “smp”). It seems to work on Android at least (good for them, that’s their main platform), while on Desktop Linux it even mostly works, but screenshots remain black.
Doom3 BFG Edition does exactly what I described earlier: They do all the window handling etc in the main thread, and run the game logic and renderer “frontend” (which only prepares draw calls, deciding what to draw etc, but doesn’t call OpenGL functions itself) in a separate thread - and this works (see also this article).
While this is OpenGL specific, I wouldn’t bet on it being better with (all) other graphics APIs (on all relevant platforms) - and as the SDL documentation explicitly recommends using the main thread, I’d just stick to that.
I entirely agree, and it’s what I do, but it means there’s a bottleneck in the inter-thread communication. The only way I’ve managed to achieve an acceptable performance is for the main thread to busy-wait on the incoming messages from the worker thread, which is obviously wasteful of CPU time (it basically ties up one core 100%).
I’ve experimented with SDL’s semaphores to improve the efficiency - the main thread waiting in SDL_SemWait and the worker thread calling SDL_SemPost when it has a message - but the latency is just too high.
I think what you need is not a semaphore but a condition variable that the main thread waits on until the worker signals it
I think I tried that too. As far as I could tell, the latency arose because of having to ‘wake up’ the waiting thread from a suspended state, which I would expect to be the same for both methods.
how big were the latencies there?
Sorry, this was years ago and I don’t remember. All I know is that the performance increased markedly by running a busy-wait loop (it’s not quite as crazy as it sounds: I only run it for 40 ms after the last message from the worker thread was received, then it does wait on a semaphore). At its peak there is a lot of inter-thread communication and even a small latency for each message adds up compared with spinning on
You definitely shouldn’t wake the thread up for every single input event or something.
Ideally this kind of synchronization is only needed once or twice per frame.
I only run it for 40 ms
that’s more than two frames at 60fps?
Anything less than a frame could introduce an unpredictable, pseudo-random, bandwidth variation to the inter-thread messaging, which could result in all sorts of artefacts. When there’s frame-rate motion, I want to know that the messages will always arrive promptly; when there’s not, I can afford the latency.