Reputation: 23
I'm trying to load textures for an SDL2 program in a separate thread for a loading screen. My code looks something like this
int batchLoad(void *ptr) {
loop through resources
SDL_LockMutex(renderMutex);
SDL_Texture *texture = NULL;
SDL_Surface *surface = IMG_Load(("../resources/" + fileName).c_str());
if (surface) {
texture = SDL_CreateTextureFromSurface(renderer, surface);
SDL_FreeSurface(surface);
}
SDL_UnlockMutex(renderMutex);
// store texture
return 0;
}
void LoadingScreen::loadResources() {
// do some stuff
renderMutex = SDL_CreateMutex();
ScreenMap screenMap;
// init with data
SDL_Thread* load = SDL_CreateThread(batchLoad, "batchLoad", &screenMap);
while loading {
// do work
SDL_LockMutex(renderMutex);
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, white, NULL, NULL);
// draw stuff
SDL_RenderPresent(renderer);
SDL_UnlockMutex(renderMutex);
}
SDL_WaitThread(load, NULL);
SDL_DestroyMutex(renderMutex);
SDL_DestroyMutex(satMutex);
On Windows this works perfectly fine, but on OSX I get an error at the CreateTextureFromSurface call. It segfaults with a null pointer error. Here's the osx problem report.
Thread 10 Crashed:: batchLoad
0 libGL.dylib 0x00007fff885ead32 glGenTextures + 18
Thread 10 crashed with X86 Thread State (64-bit):
rax: 0x0000000000000000 rbx: 0x00007ff913c37ad0 rcx: 0x0000000000000001 rdx: 0x00007ff913c37b50
rdi: 0x0000000000000001 rsi: 0x00007ff913c37b50 rbp: 0x00000001157ae4d0 rsp: 0x00000001157ae4d0
r8: 0x0000000000000004 r9: 0x00007ff913c00000 r10: 0x0000000023f4e094 r11: 0x000000000abea012
r12: 0x00007ff913d1e3b0 r13: 0x00007ff913d1e3b0 r14: 0x000000000000001a r15: 0x0000000000000022
rip: 0x00007fff885ead32 rfl: 0x0000000000010246 cr2: 0x0000000000000000
and lldb
* thread #9: tid = 0xee08, 0x00007fff885ead32 libGL.dylib`glGenTextures + 18, name = 'batchLoad', stop reason = EXC_BAD_ACCESS (code=1, address=0x0)
frame #0: 0x00007fff885ead32 libGL.dylib`glGenTextures + 18
libGL.dylib`glGenTextures + 18:
-> 0x7fff885ead32: movq (%rax), %rdi
0x7fff885ead35: movq 0x318(%rax), %rax
0x7fff885ead3c: movl %ecx, %esi
0x7fff885ead3e: popq %rbp
when I comment out all the thread stuff and just call batch load normally, there are no errors so I figured there has to be some concurrency issue. But I'm using a mutex for all of the renderer calls so I'm not sure what the issue could be. And then I also don't know why it would work fine on Windows but not on OSX
Upvotes: 2
Views: 1486
Reputation: 361
The renderer API isn't designed to be called from more than one thread (regardless of any locking being done) due to OpenGL's rules related to multi-threading. This warning is mentioned on the CategoryRender page and there's a link to a bug report where you can read more details about why it is this way and how you can work around it.
The simplest fix would be to load the surface on some background thread then hand it off to your renderer thread to be loaded into a texture.
Upvotes: 2