| Summary: | batching makes sw renderer thread-unsafe | ||
|---|---|---|---|
| Product: | SDL | Reporter: | Stas Sergeev <stsp2> |
| Component: | render | Assignee: | Ryan C. Gordon <icculus> |
| Status: | ASSIGNED --- | QA Contact: | Sam Lantinga <slouken> |
| Severity: | enhancement | ||
| Priority: | P2 | CC: | amaranth72 |
| Version: | HG 2.0 | ||
| Hardware: | x86_64 | ||
| OS: | Linux | ||
All SDL_Render functionality (including objects owned by SDL_Render like textures) is already only meant to be used from the main thread. See the documentation here: https://wiki.libsdl.org/CategoryRender and here: https://hg.libsdl.org/SDL/file/5bb9c1e57e52/include/SDL_render.h Yes, the current situation is as you say. I just think it would make sense to locate and report such occurences so that eventually there are none, at least in an SW renderer. Even if all of SDL_Render's code was completely atomic with respect to every API call (which seems like a non-goal in the first place), it still wouldn't make it usable on multiple threads on most platforms, because OpenGL is inherently single-threaded. If you want increased performance, hardware-accelerated backends as well as other possible optimizations within those backends like draw call batching are the way to go, rather than the extremely complex and costly changes that would be needed to make SDL_Render usable in multiple threads. Yes, I realize that currently only SW renderer can benefit from threading. Actually it can benefit quite a lot, as no other "HW acceleration" than threading, is possible for SW renderer. So by disallowing that, you are risking to make SW renderer completely useless. Also note that eventually probably (not sure) SDL may support vulkan as a rendering back-end, and the problem will re-surface. As it is, it may be better to consider this ticket as an RFE. |
Batching adds a dependency between renderer and texture. Like this: #2 0x00007ffff6b05787 in SW_RunCommandQueue (renderer=0x555556827c80, cmd=0x7fff60000ba0, vertices=0x555556c00440, vertsize=<optimized out>) at /home/stas/src/SDL/src/render/software/SDL_render_sw.c:714 #3 0x00007ffff6ad8976 in FlushRenderCommands (renderer=0x555556827c80) at /home/stas/src/SDL/src/render/SDL_render.c:221 #4 0x00007ffff6ad8a12 in FlushRenderCommandsIfTextureNeeded ( texture=texture@entry=0x555556b43780) at /home/stas/src/SDL/src/render/SDL_render.c:244 #5 0x00007ffff6ada69f in SDL_UpdateTexture_REAL (texture=0x555556b43780, rect=0x7fffa7706a30, pixels=0x5555577e0838, pitch=2880) at /home/stas/src/SDL/src/render/SDL_render.c:1572 #6 0x00007ffff6ac5ee2 in SDL_UpdateTexture (a=<optimized out>, b=<optimized out>, c=<optimized out>, d=<optimized out>) So the call to SDL_UpdateTexture() flushes the renderer queue (which would be empty w/o batching I think, at least no crash w/o batching). If some other thread also does something with the renderer, you get crash. So the only work-around is to use a "giant" lock that covers both texture and renderer. Thread-safe api should allow a lock per resource and no implicit dependencies.