Skocz do zawartości

[Delphi][OpenGL]Renderowanie wielowątkowe


Brainer

Polecane posty

Hej. :)

 

Chcę sobie zrobić program, który renderowałby grafikę przy użyciu wątków za pomocą klasy TThread. Oto kodzik:

 

{

               .:  Brainer's OpenGL Framework  :.
Y        [N
]Z][bG&6ćW6&Vvć6uusGGv6gGv&2ćźź((QĄąŃŃibute it and/or
   modify it under the terms of the GNU Les[[XXX[HXYHHYH&RfVćFFVFW fW'6\"bFRĆ6V6R\"ŃąŃ(((QĄątributed in the hope that it will be
   useful, but WITHOUTSHTSN]]][H[YY[HQTD$E\"dDU52d\"%D5T U%4R6VRFR9T1Aą1(Ńą))t UMain;

interface

{$WARNINGS OFF}
{$HINTS OFF}
[YY][X[726G&2f&2FĆw2VtWfG3Ś67@AM}M5==Y()Ń(QI        QąQĄ(QIBTriangleThread = class(TThread)
 protected
   { ProtectedX][bYH^X]J
NYN[D&VUVEF&VBD&VUVEF&VB6Ć72EF&V(ŃŃ(AŃŃąŃ(ecute(); override;
 end;

 { .:  TMainForm  :. }
 TMainFoHHĘJBX][][X][][&6VGW&Rf&FW7G&6VćFW#D&ŚV7B&6VGW&RfIĄMQ=(
ŃĄMQbject);
   procedure ApplicationEventsIdle(Sender: TObject;NX[NYHTZ[
[X
&fFP&fFRFV6Ć&F2&6VGW&RF&VćI        Qą(I      ąE(ą(   { Public declarations }
   DC: HDC;
   RC: HGLRC;
   S[YKN[
[N[Y&6VGW&RćDVt&6VGW&R6WGWVf&BD3!(IM((MŃŃQg();
   function GetTimeElapsed(): Single;
   procedure Di^QĘ[U[YN[JN[XZ[Nf&ÓG&ćvĆSE$t%G&ćvĆUF&VCVCD&VUVEF()ąŃŃ()H()QI     QąQĄ

procedure TRGBTriangleThread.Execute;
begin
 while not TeZ[]YY[X][ÓYYĘ
Nć6&ćŚRf&F&VćFW%$t%G&ćvĆRVćCŚVćCD&VEQĄ()Q   ąEQĄŃ)(Ąe not Terminated do
 begin
   Application.ProcessMessages(N[^JXZ[K[YT]XY
N[[Df&&6VGW&RDf&Ć6FWfVG4FĆR6VćFQ=      ą)(ąŃQMą)n
 Done := False;

 deltaTime := GetTimeElapsed();
 Displ^QĘ[U[YJN[[J
N[YHXZ[F7Će267BFVFFS6ćvĆRŚ&Vv7F'EFćrALALŹźąŃQ(%ĄAM(ĄAM= FPS_SMOOVE) then
 begin
   FPSC := 0;
   FPS := (FPS / ÓSÓJN[HX]
       NX[ÓKH  Kbg2b33e5e2ŁVćCŚVćC&6VGW&RDII        Qą)(ąQąŃ-6.0);
 glBegin(GL_TRIANGLES);
   glColor3f(1.0, 0.0, 0.0)^K
NK
NfW'FW6bÓÓv6Ć#6bvfŃ(ą)()Q5DoRenderBlueQuad;
begin
 glTranslatef(3.0, 0.0, 0.0);
 glCKKK
NY[ÓUPQĘN^LvfW'FW6bvfW'FW6b(ąYŃ(ąend;

procedure TMainForm.FormCreate(Sender: TObject);
begin]YTX[Q]Y[JJNHHG&ćvĆRŁE$t%G&ćvĆUF&VB7&VFRG'VRVBŁ       ąEQĄ
ŃĄQ((ŃĄ!ą(MŃixelFormat(DC);

 RC := wglCreateContext(DC);
 wglMakeCurr[
ĘN[][Ó

NX[K[YJ
N]XYVRŚVćC&6VGW&RDf&f&FW7G&6VćFW#D&ŚV7B)(Qą(E)()Q5inForm.FormPaint(Sender: TObject);
begin
 RenderScene();
enYHXZ[KT^J[X
NY[vfWw'BvGFVvBvG&FRt$T5D8(ą1%ŃŃ(Ą!ĄŃĄ(!Ą1;
 gluPerspective(60.0, (Width / Height), 0.1, 100.0);
 gX]^[JÓÓSŃSQUĘN[[[XZ[K][YQ[6VC6ćvĆSf CCcCŚ&VvVW'W&f&ć6T6VFĄP(IąĄPMŃŃQź)()edure TMainForm.InitOpenGL;
begin
 glClearColor(0.0, 0.0, 0
N[XJÓŃTT
NXJÓĘNv7VĆf6Rt$4ŚVćC&6VGW&RDf&&VćFW%66Vć)(ą
ąĄ1}
=1=I}   UI}  %P1}AQ!} UI}  %P;
 glLoadIdentity();

 SwapBuffers(DC);
end;

procedure TMZ[K]^[X]
ĘNVSPUU45$D\"6ŚS6ŚTbETd$DDU45$D\"Y(ąA}MUAA=IQ}=A90A}I]}Q=}INDOW or
     PFD_DOUBLEBUFFER;
   iPixelType: PFD_TYPE_RGN]Y]YYŃ&VV&G34w&VV6gC4&VT&G34&VU6gC(ąĄ ŃąĄMĄ(     Ń(cAccumRedBits: 0;
   cAccumGreenBits: 0;
   cAccumBlueBitsX[P[P]Ń]M[[&G34W'VffW'3ĆW%GSdESI(15Ź(Yą5Ź(   dwDamageMask: 0;
  );
var
 pixelFormat: Integer;
begin
^[X]HT^[X]

NY]^Vf&BD2Vf&BfBFVWCŚVćC&6VGWQ5MŃŃQ)(EA
ŃĄMŃtTime);
end;

end.

 

Czemu to nie działa? :blink:

Jeśli wykonam ten kodzik bez użycia wątków, to wszystko śmiga elegancko.

 

Z góry dzięki! :D

Link do komentarza
Udostępnij na innych stronach

CYTAT(Toster @ śro, 27 cze 2007 - 11:25) moze zadam glupiue pytanie ale: co nie dziala ?

 

Nie działa renderowanie! Nic się nie wyświetla.

 

po drugie z tego ce zerknalem uzywasz synchronize czyli de facto wszystko zwalnia bo masz tam waskie gardlo.

 

W takim razie, podaj jakąś inną metodę na to, żeby to realizować wątkami. Może BeginThread? :blink:

Link do komentarza
Udostępnij na innych stronach

synchronize de facto zapewnia ci ze podana metoda zostanie wywolana z glownego watku, czyli jak masz 10 watkow ktore beda renderowac to tak naprawde ustawia sie one ladnie pod drzwiami i tylko jedne w jednej chwili bedzie renderowal inne beda czekac.

 

Metod synchronizacji jest kilka:

1. Critical section

2. Semafory

3. Mutexy

4. Synchronize

5. Message

 

i pewnie n o ktorych nie slyszalem.

 

Aby zrobic wydajny system wielowatkowy nie wystarczy siasc i napisac kod uzywajac klasy obudowujacej watek, tylko trzeba najpierw wszystko zaprojektowac i dobrac architekture ktora najlepiej spelni swoje zadanie (trzeba tylko wiedziec co jest dla ciebie najwazniejsze)

 

Inna sprawa ze karty maja kilka potokow renderujacych wiec proponowalbym poczytac o tym i uzyc mechnizmow ktore zostaly do tego stworzone i pod tym katem zoptymalizowane

Always Dark<br />u1_tt_logo.png banner-1.pngexFabula-banner.pngson_banner_ubersmall.jpg

Link do komentarza
Udostępnij na innych stronach

Hehe, dzięki za odpowiedź! :)

 

Przeczytałem na GameDev.net, że OpenGL nie jest bezpieczne wątkowo (thread-safe), czyli dwa wątki nie mogą wywoływać poleceń OpenGL. Z drugiej strony, jeden z userów napisał, że możliwa jest synchronizacja wątków przy pomocy sekcji krytycznych.

Prawdę powiedziawszy, nigdy wcześniej nie próbowałem używać wątków bez korzystania z klasy TThread i funkcji BeginThread. Chyba najwyższy czas spróbować. :D

 

Przy okazji, masz jakieś tutoriale na temat sekcji krytycznych? Obojętnie czy w Delphi, czy w C++. Znam oba. :P Gdzieś kiedyś miałem książkę, w której było napisane o tych sekcjach (bodajże Delphi 6. Vademecum profesjonalisty). Muszę zerknąć...

 

Dzięki za odpowiedź, Toster! :)

Link do komentarza
Udostępnij na innych stronach

Przepraszam, ale jaki sens ma Application.ProcessMessages(); w wątku (innym niż główny) ?

 

To polecenie pozwala przetworzyć komunikaty wysyłane do okienka. :) Kiedyś gdzieś widziałem użycie tego polecenia w wątkach pobocznych. Ale ja też nie widzę sensu jego użycia. :P

Link do komentarza
Udostępnij na innych stronach

bo glowny watek jak nie jest w procce to w idlu sam pobiera message.

A watki poboczne nie musza mu w tym pomagac.

Pozatym nie dajac sleepa watkowi zamulasz mocno ssytem i nie dajesz czasu innym watka aby sobie poszalaly :)

Tak czy siak w glownej pewli watkow zazwyczaj daje sie jakiegos malego sleepa np 10-50 ms. Zalezy tez do czego waki sa, bez sensu np mielic 100% CPU na watku ktory czeka na polaczenie sieciowe, mozesz go uspic na 100ms a pozniej sprawdzic czy cos sie zmienilo, jesli tak to zaczac cos robic jesli nie to znowu idziesz spac.

 

czesto jest tak ze jeden watek czeka az sie cos wydarzy (np drugi watek cos skonczy, albo na dostep do jakis zasobow) w tym czasie moze sie spokojnie przekimac zanim ponowi probe.

Always Dark<br />u1_tt_logo.png banner-1.pngexFabula-banner.pngson_banner_ubersmall.jpg

Link do komentarza
Udostępnij na innych stronach

To polecenie pozwala przetworzyć komunikaty wysyłane do okienka. :) Kiedyś gdzieś widziałem użycie tego polecenia w wątkach pobocznych. Ale ja też nie widzę sensu jego użycia. :P

Wiem, co wykonuje ProcessMsgs. Ale w wątku to IMO nie ma kompletnie sensu.

 

1. Jeśli nie synchronizujesz niczego przez TThread.Synchronize(), to wątek główny i tak się wykonuje więc sam przetwarza komunikaty.

2. Jeśli synchronizujesz, to i tak ProcessMsgs nic nie da w tym miejscu. Prędzej gdzieś w procedurze synchronizowanej.

 

No, ale to OT ;-)

 

EDIT: Spóźniłem się ;-)

҉

Link do komentarza
Udostępnij na innych stronach

Zarchiwizowany

Ten temat jest archiwizowany i nie można dodawać nowych odpowiedzi.

Gość
Temat jest zablokowany i nie można w nim pisać.
×
×
  • Utwórz nowe...