Recent

Author Topic: [SOLVED] Why does rendering in thread doesn't work?  (Read 4952 times)

Pascal

  • Hero Member
  • *****
  • Posts: 932
[SOLVED] Why does rendering in thread doesn't work?
« on: July 03, 2017, 09:40:35 am »
I am going to put my gl rendering into a thread but i can't get it gooing.
If i put the rendering in a OnTimer-Event it works but if i call the
same OnTimer-Event in my thread it doesn't work.

OnTimer-event:
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Timer1Timer(Sender: TObject);
  2. var
  3.   Speed: Double;
  4. begin
  5.   glEnable(GL_DEPTH_TEST);
  6.   glDepthFunc(GL_GEQUAL);
  7.   glEnable(GL_TEXTURE_2D);
  8.   glClearDepth(0);
  9.  
  10.   glClearColor(0.0, 0.0, 0.0, 0.0);
  11.   glClear(GL_DEPTH_BUFFER_BIT or GL_COLOR_BUFFER_BIT);
  12.   glMatrixMode(GL_PROJECTION);
  13.   glLoadIdentity();
  14.   //glViewport(0,0, pWidth, pHeight);
  15.   glOrtho(0, fProject.Width, fProject.Height, 0, -256, 256);
  16.   //gluPerspective(45.0, width / height, 0.1, 100.0);
  17.   glMatrixMode(GL_MODELVIEW);
  18.   glLoadIdentity();
  19.   glEnable(GL_BLEND);
  20.   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  21.  
  22.   fSlide.Render(0);
  23.  
  24.   OpenGLControl1.SwapBuffers;
  25. end;

Thread:
Code: Pascal  [Select][+][-]
  1.   TPreview = class(TThread)
  2.   private
  3.     fProc: TNotifyEvent;
  4.   protected
  5.     procedure Execute; override;
  6.   public
  7.     constructor Create(pProc: TNotifyEvent);
  8.   end;
  9.   .
  10.   .
  11.   .
  12. implementation
  13.  
  14. procedure TPreview.Execute;
  15. begin
  16.   while not Terminated do begin
  17.     fProc(nil);
  18.     Sleep(40);
  19.   end;
  20. end;
  21.  
  22. constructor TPreview.Create(pProc: TNotifyEvent);
  23. begin
  24.   inherited Create(true);
  25.   fProc := pProc;
  26. end;
  27.  
« Last Edit: July 03, 2017, 01:39:38 pm by Pascal »
laz trunk x64 - fpc trunk i386 (cross x64) - Windows 10 Pro x64 (21H2)

Cyrax

  • Hero Member
  • *****
  • Posts: 836
Re: Why does rendering in thread doesn't work?
« Reply #1 on: July 03, 2017, 10:34:33 am »
You can't call any component method(s) that interacts with LCL (paint etc), in threads. Only main thread can call these methods.

Pascal

  • Hero Member
  • *****
  • Posts: 932
Re: Why does rendering in thread doesn't work?
« Reply #2 on: July 03, 2017, 10:40:19 am »
I know, but OpenGLContext doesn't do any painting just setting up the viewport and calling OnPaint which isn't set up in my case.
So it should work.
laz trunk x64 - fpc trunk i386 (cross x64) - Windows 10 Pro x64 (21H2)

Thaddy

  • Hero Member
  • *****
  • Posts: 14382
  • Sensorship about opinions does not belong here.
Re: Why does rendering in thread doesn't work?
« Reply #3 on: July 03, 2017, 10:52:23 am »
The rendering in the thread is not an issue, provided you protect the rendering code with a critical section.
But you need to call OpenGLControl1.SwapBuffers; in the context of the main thread. Not IN the thread. Or Syncronize(SwapBuffers), that's also possible.
The latter is more or less the same, but easier with your code and does not need a critical section, although I would recommend it anyway.
« Last Edit: July 03, 2017, 10:57:45 am by Thaddy »
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

Pascal

  • Hero Member
  • *****
  • Posts: 932
Re: Why does rendering in thread doesn't work?
« Reply #4 on: July 03, 2017, 12:10:45 pm »
Thaddy, thanks for the tip.

Unfortunately that doesn't make any difference  :(

Code: Pascal  [Select][+][-]
  1. type
  2.   TSimple = procedure of object;
  3.  
  4.   TPreview = class(TThread)
  5.   private
  6.     fControl: TOpenGLControl;
  7.     fProc: TNotifyEvent;
  8.     fInit: TSimple;
  9.     procedure SwapBuffers;
  10.   protected
  11.     procedure Execute; override;
  12.   public
  13.     constructor Create(pInit: TSimple; pProc: TNotifyEvent; pControl: TOpenGLControl);
  14.   end;
  15.  
  16.  
  17. implementaion
  18.  
  19. procedure TPreview.SwapBuffers;
  20. begin
  21.   fControl.SwapBuffers;
  22. end;
  23.  
  24. procedure TPreview.Execute;
  25. var
  26.   t: QWord;
  27. begin
  28.   fInit;
  29.   while not Terminated do begin
  30.     t := GetTickCount64;
  31.     fProc(nil);
  32.     if not Terminated then begin
  33.       //Synchronize(@SwapBuffers);
  34.       t := 40 - (GetTickCount64 - t);
  35.       if t > 0 then Sleep(t);
  36.     end;
  37.   end;
  38. end;
  39.  
  40. constructor TPreview.Create(pInit: TSimple; pProc: TNotifyEvent;
  41.   pControl: TOpenGLControl);
  42. begin
  43.   inherited Create(true);
  44.   fControl := pControl;
  45.   fInit := pInit;
  46.   fProc := pProc;
  47. end;
laz trunk x64 - fpc trunk i386 (cross x64) - Windows 10 Pro x64 (21H2)

Thaddy

  • Hero Member
  • *****
  • Posts: 14382
  • Sensorship about opinions does not belong here.
Re: Why does rendering in thread doesn't work?
« Reply #5 on: July 03, 2017, 12:16:18 pm »
What I was hinting at is the following:
You do the full rendering in the thread, on the current off-line buffer. Then call synchronize(swapbuffers). You are doing the painting somewhere else.
Object Pascal programmers should get rid of their "component fetish" especially with the non-visuals.

Pascal

  • Hero Member
  • *****
  • Posts: 932
Re: Why does rendering in thread doesn't work?
« Reply #6 on: July 03, 2017, 12:42:24 pm »
The painting is done in the OnTimerEvent (which is called by the thread (Testcase)):
Code: Pascal  [Select][+][-]
  1. procedure TForm1.Timer1Timer(Sender: TObject);
  2. var
  3.   Speed: Double;
  4. begin
  5.   OpenGLControl1.MakeCurrent;
  6.   glEnable(GL_DEPTH_TEST);
  7.   glDepthFunc(GL_GEQUAL);
  8.   glEnable(GL_TEXTURE_2D);
  9.   glClearDepth(0);
  10.  
  11.   glClearColor(1.0, 0.0, 0.0, 0.0);
  12.   glClear(GL_DEPTH_BUFFER_BIT or GL_COLOR_BUFFER_BIT);
  13.   glMatrixMode(GL_PROJECTION);
  14.   glLoadIdentity();
  15.   glViewport(0,0, OpenGLControl1.Width, OpenGLControl1.Height);
  16.   glOrtho(0, fProject.Width, fProject.Height, 0, -256, 256);
  17.   //gluPerspective(45.0, width / height, 0.1, 100.0);
  18.   glMatrixMode(GL_MODELVIEW);
  19.   glLoadIdentity();
  20.   glEnable(GL_BLEND);
  21.   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  22.   fSlide.Render(0);
  23.   OpenGLControl1.SwapBuffers;
  24. end;
  25.  

Slide.Renderer:
Code: Pascal  [Select][+][-]
  1. procedure TEPSlide.Render(pTime: Int64);
  2. var
  3.   o: TEPSlideObject;
  4.   z: GLfloat;
  5. begin
  6.   z := 128;
  7.   for o in fObjects do begin
  8.     o.Render(pTime, z);
  9.     z := z - 1
  10.   end;
  11. end;
  12.  

Picture Renderer: (Slide contains on TEPPicture)
Code: Pascal  [Select][+][-]
  1. procedure TEPPicture.Render(pTime: Int64; pZ: GLfloat);
  2. begin
  3.   glBindTexture(GL_TEXTURE_2D, FTexture);
  4.   glBegin(GL_QUADS);
  5.     glTexCoord2f(0,0); glVertex3f(FLeft,          FTop + FHeight, pZ);
  6.     glTexCoord2f(1,0); glVertex3f(FLeft + FWidth, FTop + FHeight, pZ);
  7.     glTexCoord2f(1,1); glVertex3f(FLeft + FWidth, FTop,           pZ);
  8.     glTexCoord2f(0,1); glVertex3f(FLeft,          FTop,           pZ);
  9.   glEnd;
  10.  
  11.   glColor4f(1.0, 1.0, 1.0, 1.0);
  12. end;
  13.  

So no magic here. It works in a timer but not in a thread.

laz trunk x64 - fpc trunk i386 (cross x64) - Windows 10 Pro x64 (21H2)

Pascal

  • Hero Member
  • *****
  • Posts: 932
Re: Why does rendering in thread doesn't work?
« Reply #7 on: July 03, 2017, 12:50:25 pm »
I  have an old delphi prototype where i did rendering in a thread. There everything is done in the thread
(including creating context). This prog uses dglOpenGL.pas.

Maybe i should use dglOpenGL instead of OpenGLContext and GL.
laz trunk x64 - fpc trunk i386 (cross x64) - Windows 10 Pro x64 (21H2)

Pascal

  • Hero Member
  • *****
  • Posts: 932
Re: Why does rendering in thread doesn't work?
« Reply #8 on: July 03, 2017, 01:39:14 pm »
Okay. Using dglOpenGL works as expected.
Maybe this is due to the context beeing created in the main thread.
laz trunk x64 - fpc trunk i386 (cross x64) - Windows 10 Pro x64 (21H2)

 

TinyPortal © 2005-2018