Skip to main content
added 777 characters in body
Source Link

TL,DR: If you're The SDL2 event/render system is not yet thread-safe, but you can overcome this limitation by using OpenGL to decouple the renderer system from your application (and then perform all rendering in a separate thread using only OpenGL functions). In this method, yes you canstill have a single event queue.

Another way is to use multiple processes (e.g. using PySDL2 and Python's multiprocessing module, or a C/C++ program that launches two sub-processes), and follow the same dual-window method outlined below (where each window has it's own event queue, but one window is hidden and is only polled to check for user input). One process will handle drawing and the other input, and application state changes and events are communicated between both processes using a pipe or thread-safe queue.


It's generally not recommended to separate render/input/game logic into different threads since it greatly complicates things under the hood, and you need to ensure data concurrency and thread synchronization (although SDL2 does indeed provide what you need to accomplish this). That being said, if you do need to separate input/rendering - and in this case, I agree that would be the most logical thing to do - it is possible to do using SDL2 threads (as well as Python threads if you're using PySDL2) and OpenGL.

There are two approaches to accomplishing this, one with a single-window and another with a double-window.

With a single window, create your OpenGL context/window with SDL2, then pass the OpenGL context to a new thread that will perform only rendering. It needs to safely notify the main thread when to call SDL_GL_SwapWindow and block until it's done (you can still keep polling events for the window even if you don't call GL_SwapWindow), but so long as you ensure only one thread is calling OpenGL functions at once, there is no problem doing this, even cross platform.

Using the double-window approach allows you to fully decouple all OpenGL API/rendering calls from the main loop, by using the main loop to create a hidden overlay window that captures the keyboard/mouse input, and continually polls for input/window events. This way you don't need to stop for any OpenGL calls, and so long as your application state is thread-safe, you can pass any relevant window events to the GL window in a queue.

TL,DR: If you're using OpenGL, yes you can.

It's generally not recommended to separate render/input/game logic into different threads since it greatly complicates things under the hood, and you need to ensure data concurrency and thread synchronization (although SDL2 does indeed provide what you need to accomplish this). That being said, if you do need to separate input/rendering - and in this case, I agree that would be the most logical thing to do - it is possible to do using SDL2 threads (as well as Python threads if you're using PySDL2) and OpenGL.

There are two approaches to accomplishing this, one with a single-window and another with a double-window.

With a single window, create your OpenGL context/window with SDL2, then pass the OpenGL context to a new thread that will perform only rendering. It needs to safely notify the main thread when to call SDL_GL_SwapWindow and block until it's done (you can still keep polling events for the window even if you don't call GL_SwapWindow), but so long as you ensure only one thread is calling OpenGL functions at once, there is no problem doing this, even cross platform.

Using the double-window approach allows you to fully decouple all OpenGL API/rendering calls from the main loop, by using the main loop to create a hidden overlay window that captures the keyboard/mouse input, and continually polls for input/window events. This way you don't need to stop for any OpenGL calls, and so long as your application state is thread-safe, you can pass any relevant window events to the GL window in a queue.

TL,DR: The SDL2 event/render system is not yet thread-safe, but you can overcome this limitation by using OpenGL to decouple the renderer system from your application (and then perform all rendering in a separate thread using only OpenGL functions). In this method, you still have a single event queue.

Another way is to use multiple processes (e.g. using PySDL2 and Python's multiprocessing module, or a C/C++ program that launches two sub-processes), and follow the same dual-window method outlined below (where each window has it's own event queue, but one window is hidden and is only polled to check for user input). One process will handle drawing and the other input, and application state changes and events are communicated between both processes using a pipe or thread-safe queue.


It's generally not recommended to separate render/input/game logic into different threads since it greatly complicates things under the hood, and you need to ensure data concurrency and thread synchronization (although SDL2 does indeed provide what you need to accomplish this). That being said, if you do need to separate input/rendering - and in this case, I agree that would be the most logical thing to do - it is possible to do using SDL2 threads (as well as Python threads if you're using PySDL2) and OpenGL.

There are two approaches to accomplishing this, one with a single-window and another with a double-window.

With a single window, create your OpenGL context/window with SDL2, then pass the OpenGL context to a new thread that will perform only rendering. It needs to safely notify the main thread when to call SDL_GL_SwapWindow and block until it's done (you can still keep polling events for the window even if you don't call GL_SwapWindow), but so long as you ensure only one thread is calling OpenGL functions at once, there is no problem doing this, even cross platform.

Using the double-window approach allows you to fully decouple all OpenGL API/rendering calls from the main loop, by using the main loop to create a hidden overlay window that captures the keyboard/mouse input, and continually polls for input/window events. This way you don't need to stop for any OpenGL calls, and so long as your application state is thread-safe, you can pass any relevant window events to the GL window in a queue.

deleted 763 characters in body
Source Link

TL,DR: If you're using OpenGL, yes you can.

It's generally not recommended to separate render/input/game logic into different threads since it greatly complicates things under the hood, and you need to ensure data concurrency and thread synchronization (although SDL2 does indeed provide what you need to accomplish this). That being said, if you do need to separate input/rendering - and in this case, I agree that would be the most logical thing to do - it is possible to do using SDL2 threads (as well as Python threads if you're using PySDL2) and OpenGL.

The trick here is to use multiple windows. While indeed you can't poll a window's events from multiple threads, you can run two separate event loops, forThere are two separate windows, in parallel. One window is used purely for rendering/drawing, and the other window is used purely for handling input (and either updating the application logicapproaches to accomplishing this, or sending input events [which could then be timestamped] inone with a queue to the main render threadsingle-window and update the application logic there)another with a double-window.

How you do this is entirely up to you - one possible way I've had success with is toWith a single window, create your main render windowOpenGL context/event loop as normalwindow with SDL2, and then startpass the OpenGL context to a secondnew thread that creates another secondary, small window, using the HIDDEN window flagswill perform only rendering. Lastly, in your render thread, ensure when It needs to safely notify the main/render window is in focus thread when to call SDL_GL_SwapWindow and block until it's done (oryou can still keep polling events for the window even if you get a FOCUS_GAINED/EVENT_ENTER event in your render loopdon't call GL_SwapWindow), but so long as you use SDL_RaiseWindow to always ensure your hidden input-capture window has focusonly one thread is calling OpenGL functions at once, there is no problem doing this, even cross platform.


 

That being said, it would probably be bestUsing the double-window approach allows you to keep your main threadfully decouple all OpenGL API/window looprendering calls from the "blank" windowmain loop, andby using the main loop to create a secondaryhidden overlay window, in another thread that captures the keyboard/mouse input, purelyand continually polls for rendering (following the same approach of ensuring the input goes to the "blank" window)/window events. That This way you could easily re-create your render window if it gets closed for some reason.

Since you can probably keep your application logic in the render loop,don't need to simplify the overall implementation, your second thread/window should probably do nothingstop for exceptany poll for input events. You could then add the input event to aOpenGL calls, and so long as your application state is thread-safe queue along with the current time via SDL_GetTicks (or using the high performance timer if you need more accuracy). Finally, in your main loop, each frame, you can just go through the queue and handle thepass any relevant window events as normal, except now you know exactly whento the event occurredGL window in a queue.

It's generally not recommended to separate render/input/game logic into different threads since it greatly complicates things under the hood, and you need to ensure data concurrency and thread synchronization (although SDL2 does indeed provide what you need to accomplish this). That being said, if you do need to separate input/rendering - and in this case, I agree that would be the most logical thing to do - it is possible to do using SDL2 threads (as well as Python threads if you're using PySDL2).

The trick here is to use multiple windows. While indeed you can't poll a window's events from multiple threads, you can run two separate event loops, for two separate windows, in parallel. One window is used purely for rendering/drawing, and the other window is used purely for handling input (and either updating the application logic, or sending input events [which could then be timestamped] in a queue to the main render thread and update the application logic there).

How you do this is entirely up to you - one possible way I've had success with is to create your main render window/event loop as normal, and then start a second thread that creates another secondary, small window, using the HIDDEN window flags. Lastly, in your render thread, ensure when the main/render window is in focus (or you get a FOCUS_GAINED/EVENT_ENTER event in your render loop) you use SDL_RaiseWindow to always ensure your hidden input-capture window has focus.


 

That being said, it would probably be best to keep your main thread/window loop the "blank" window, and create a secondary window, in another thread, purely for rendering (following the same approach of ensuring the input goes to the "blank" window). That way you could easily re-create your render window if it gets closed for some reason.

Since you can probably keep your application logic in the render loop, to simplify the overall implementation, your second thread/window should probably do nothing except poll for input events. You could then add the input event to a thread-safe queue along with the current time via SDL_GetTicks (or using the high performance timer if you need more accuracy). Finally, in your main loop, each frame, you can just go through the queue and handle the events as normal, except now you know exactly when the event occurred.

TL,DR: If you're using OpenGL, yes you can.

It's generally not recommended to separate render/input/game logic into different threads since it greatly complicates things under the hood, and you need to ensure data concurrency and thread synchronization (although SDL2 does indeed provide what you need to accomplish this). That being said, if you do need to separate input/rendering - and in this case, I agree that would be the most logical thing to do - it is possible to do using SDL2 threads (as well as Python threads if you're using PySDL2) and OpenGL.

There are two approaches to accomplishing this, one with a single-window and another with a double-window.

With a single window, create your OpenGL context/window with SDL2, then pass the OpenGL context to a new thread that will perform only rendering. It needs to safely notify the main thread when to call SDL_GL_SwapWindow and block until it's done (you can still keep polling events for the window even if you don't call GL_SwapWindow), but so long as you ensure only one thread is calling OpenGL functions at once, there is no problem doing this, even cross platform.

Using the double-window approach allows you to fully decouple all OpenGL API/rendering calls from the main loop, by using the main loop to create a hidden overlay window that captures the keyboard/mouse input, and continually polls for input/window events. This way you don't need to stop for any OpenGL calls, and so long as your application state is thread-safe, you can pass any relevant window events to the GL window in a queue.

Post Undeleted by Breakthrough
Post Deleted by Breakthrough
added 334 characters in body
Source Link

It's generally not recommended to separate render/input/game logic into different threads since it greatly complicates things under the hood, and you need to ensure data concurrency and thread synchronization (although SDL2 does indeed provide what you need to accomplish this). That being said, if you do need to separate input/rendering - and in this case, I agree that would be the most logical thing to do - it is possible to do using SDL2 threads (as well as Python threads if you're using PySDL2).

The trick here is to use multiple windows. While indeed you can't poll a window's events from multiple threads, you can run two separate event loops, for two separate windows, in parallel. One window is used purely for rendering/drawing, and the other window is used purely for handling input (and either updating the application logic, or sending input events [which could then be timestamped] in a queue to the main render thread and update the application logic there).

How you do this is entirely up to you - one possible way I've had success with is to create your main render window/event loop as normal, and then start a second thread that creates another secondary, small window, using the HIDDEN window flags. Lastly, in your render thread, ensure when the main/render window is in focus (or you get a FOCUS_GAINED/EVENT_ENTER event in your render loop) you use SDL_RaiseWindow to always ensure your hidden input-capture window has focus.


That being said, it would probably be best to keep your main thread/window loop the "blank" window, and create a secondary window, in another thread, purely for rendering (following the same approach of ensuring the input goes to the "blank" window). That way you could easily re-create your render window if it gets closed for some reason.

Since you can probably keep your application logic in the render loop, to simplify the overall implementation, your second thread/window should probably do nothing except poll for input events. You could then add the input event to a thread-safe queue along with the current time via SDL_GetTicks (or using the high performance timer if you need more accuracy). Finally, in your main loop, each frame, you can just go through the queue and handle the events as normal, except now you know exactly when the event occurred.

It's generally not recommended to separate render/input/game logic into different threads since it greatly complicates things under the hood, and you need to ensure data concurrency and thread synchronization (although SDL2 does indeed provide what you need to accomplish this). That being said, if you do need to separate input/rendering - and in this case, I agree that would be the most logical thing to do - it is possible to do using SDL2 threads (as well as Python threads if you're using PySDL2).

The trick here is to use multiple windows. While indeed you can't poll a window's events from multiple threads, you can run two separate event loops, for two separate windows, in parallel. One window is used purely for rendering/drawing, and the other window is used purely for handling input (and either updating the application logic, or sending input events [which could then be timestamped] in a queue to the main render thread and update the application logic there).

How you do this is entirely up to you - one possible way I've had success with is to create your main render window/event loop as normal, and then start a second thread that creates another secondary, small window, using the HIDDEN window flags. Lastly, in your render thread, ensure when the main/render window is in focus (or you get a FOCUS_GAINED/EVENT_ENTER event in your render loop) you use SDL_RaiseWindow to always ensure your hidden input-capture window has focus.


That being said, it would probably be best to keep your main thread/window loop the "blank" window, and create a secondary window, in another thread, purely for rendering (following the same approach of ensuring the input goes to the "blank" window). That way you could easily re-create your render window if it gets closed for some reason.

It's generally not recommended to separate render/input/game logic into different threads since it greatly complicates things under the hood, and you need to ensure data concurrency and thread synchronization (although SDL2 does indeed provide what you need to accomplish this). That being said, if you do need to separate input/rendering - and in this case, I agree that would be the most logical thing to do - it is possible to do using SDL2 threads (as well as Python threads if you're using PySDL2).

The trick here is to use multiple windows. While indeed you can't poll a window's events from multiple threads, you can run two separate event loops, for two separate windows, in parallel. One window is used purely for rendering/drawing, and the other window is used purely for handling input (and either updating the application logic, or sending input events [which could then be timestamped] in a queue to the main render thread and update the application logic there).

How you do this is entirely up to you - one possible way I've had success with is to create your main render window/event loop as normal, and then start a second thread that creates another secondary, small window, using the HIDDEN window flags. Lastly, in your render thread, ensure when the main/render window is in focus (or you get a FOCUS_GAINED/EVENT_ENTER event in your render loop) you use SDL_RaiseWindow to always ensure your hidden input-capture window has focus.


That being said, it would probably be best to keep your main thread/window loop the "blank" window, and create a secondary window, in another thread, purely for rendering (following the same approach of ensuring the input goes to the "blank" window). That way you could easily re-create your render window if it gets closed for some reason.

Since you can probably keep your application logic in the render loop, to simplify the overall implementation, your second thread/window should probably do nothing except poll for input events. You could then add the input event to a thread-safe queue along with the current time via SDL_GetTicks (or using the high performance timer if you need more accuracy). Finally, in your main loop, each frame, you can just go through the queue and handle the events as normal, except now you know exactly when the event occurred.

added 334 characters in body
Source Link
Loading
Source Link
Loading