The SDL forums have moved to discourse.libsdl.org.
This is just a read-only archive of the previous forums, to keep old links working.


SDL Forum Index
SDL
Simple Directmedia Layer Forums
SDL_UpdateTexture crash when called from another thread...
pik33


Joined: 25 Nov 2015
Posts: 10
.. in Linux, but not in Windows.

I wrote a program (a smple SID player) with Lazarus/Freepascal (you can download it here: http://eksperymenty.edu.pl/index.php/en/sid-player/2-uncategorised/23-a-nostalgic-sid-player ).

The program works like this: it initializes SDL in the main thread, then it starts another thread, which then do all display things in the loop while the main program opens files, and does the rest of needed things.

The thread code looks like this:

Code:

procedure TRetro.Execute;

var p3:pointer;
      t:int64;

begin
running:=1;                               // tell them the machine is running

repeat
if p2<>nil then                           // the screen is prepared
  begin

  p3:=p2+2304000;                         // second frame buffer
  sdlevents;                              // get events from SDL and update system variables
  vblank1:=0;                             // tell them there is no vblank
  t:=gettime;                             // prepare for screen time measurement
  scrconvert(p2,raml^[$18001]);           // convert the screen
  tim:=gettime-t;                         // get screen time for debug
  raml^[$18000]+=1;                       // increment frame counter
  vblank1:=1;                             // we are in fake vblank now
  sprite(p2);               // draw sprites


  SDL_UpdateTexture(sdlTexture, nil, p2, 1920 * 4);   // render the screen
  SDL_RenderClear(sdlRenderer);
  SDL_RenderCopy(sdlRenderer, sdlTexture,nil,nil);
  SDL_RenderPresent(sdlRenderer);


  sdlevents;                             
  vblank1:=0;
  t:=gettime;
  scrconvert(p3,raml^[$18001]);
  tim:=gettime-t;
  raml^[$18000]+=1;
  vblank1:=1;
  sprite(p3);

  SDL_UpdateTexture(sdlTexture, nil, p3, 1920 * 4);
  SDL_RenderClear(sdlRenderer);
  SDL_RenderCopy(sdlRenderer, sdlTexture,nil,nil);
  SDL_RenderPresent(sdlRenderer);
  poke($70000,1) ;

  end;
until terminated;
running:=0;
end;


In Windows all works as expected. In Linux (Mint, x64, Nvidia 760) I got segmentation fault when using proprietary Nvidia driver or simply nothing (the SDL window with garbage copied from the background) when using Nouveau.

Then I disabled the thread and added this screen refreshing stuff to the main loop. Then it worked. Some things are of course broken, because this screen refreshing thing was supposed to run in parallel with the rest of the program, but I have a screen looking as expected.

So the obvious solution is to rewrite all the code, to make screen refresh in the main loop and the rest SDL unrelated things in another thread(s). This needs a lot of work.

Is there any solution to make this thread run or is it simply impossible in Linux to do this and I have to rewrite the code?
mr_tawan


Joined: 13 Jan 2014
Posts: 161
I think the renderer does not support multithreading. In my code I have to move all the renderer-related into the main thread otherwise it won't work.
SDL_UpdateTexture crash when called from another thread...
Jared Maddox
Guest

Quote:
Date: Wed, 20 Jan 2016 11:22:44 +0000
From: "pik33"
To:
Subject: [SDL] SDL_UpdateTexture crash when called from another
thread...
Message-ID:
Content-Type: text/plain; charset="iso-8859-1"

.. in Linux, but not in Windows.

I wrote a program (a smple SID player) with Lazarus/Freepascal (you can
download it here:
http://eksperymenty.edu.pl/index.php/en/sid-player/2-uncategorised/23-a-nostalgic-sid-player
).

The program works like this: it initializes SDL in the main thread, then it
starts another thread, which then do all display things in the loop while the
main program opens files, and does the rest of needed things.

The thread code looks like this:


<snip>

Quote:
In Windows all works as expected. In Linux (Mint, x64, Nvidia 760) I got
segmentation fault when using proprietary Nvidia driver or simply nothing
(the SDL window with garbage copied from the background) when using Nouveau.

Then I disabled the thread and added this screen refreshing stuff to the
main loop. Then it worked. Some things are of course broken, because this
screen refreshing thing was supposed to run in parallel with the rest of the
program, but I have a screen looking as expected.

So the obvious solution is to rewrite all the code, to make screen refresh in
the main loop and the rest SDL unrelated things in another thread(s). This
needs a lot of work.

Is there any solution to make this thread run or is it simply impossible in
Linux to do this and I have to rewrite the code?


Graphical adapter code should only be expected to work on the main
thread. Ths is true for all platforms. Some platforms will allow it to
work in more situations (Windows uses COM to convert multi-threaded to
single-threaded, X11 can operate fully multi-threaded in cross-network
configurations, etc.), but the only situation that you can count on is
running from the main thread. Thus, if you want multi-threaded
behavior you should leave graphics in the main thread, and push
everything else into another thread, instead of the other way around.

It might also be the case that you aren't updating the event queue
properly, but I think this is a driver issue. Cram the bulk of the
"main loop" code into a function, put a minimalist "main loop" into
the TRetro.Execute function (you need it to update the events queue),
and swap the positions of the functions.
_______________________________________________
SDL mailing list

http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
KubaBrt


Joined: 02 Jan 2016
Posts: 4
on windows you are using propably d3d driver, and you can update texture from another thread, on linux you are using Opengl for sure. In OpenGL you can access your texture only from thread where your GlContext was created. OpenGl doesnt allow to access textures from different thread.

For example on windows change your renderer to OpenGl and i asume your application will crash too as linux.

If you have to access opengl textures in another thread some option is to change driver to OpenGl ES2 and use OES_EGL_image_external texture type, according to this documentation: https://www.khronos.org/registry/gles/extensions/OES/OES_EGL_image_external.txt, opengl es2 extensions allow you to work with textures from another thread. But SDl2 doesnt support image_external by default you have to change some renderer code directly in sdl2 which isn't too easy.

So, i think you should change your architecture and access textures in render thread.
Problem solved.
pik33


Joined: 25 Nov 2015
Posts: 10
Solved.

The solution was simple: moving sdl_init, sdl_quit and all the rest of SDL initialization stuff from the main therad to the screen refreshing thread. Now all SDL calls are called from the same thread and it works with OpenGL renderer too.