Seite 1 von 1

FlipBuffers oder ähnliches in Threads

Verfasst: 16.03.2006 16:15
von KTX82
Hallo Leute!

Da man ja DX-Befehle nicht in Threads verwenden soll, aber ich unbedingt eine Technik bräuchte um unabhängig vom Hautcode einen ScreenBuffer zu flippen, meine Frage: Ist soetwas in Threads überhaupt möglich.

Nun die genaue Erklärung. Ich möchte im Prinzip 3 Buffer, einen Front-Buffer (das was sichtbar ist auf dem Monitor), einen Backbuffer (wo immer nur fertig gerenderte Bilder drin liegen, welche durch einen Thread regelmäßig auf den Frontbuffer gelegt werden), und dann den ZeichenBuffer, auf den im Hauptcode gezeichnet wird. Wenn das Bild fertig gerendert ist, soll es im Hauptcode in den Backbuffer geschoben werden, so dass sofort mit dem nächsten Renderdurchgang begonnen werden kann, ohne auf den eigentlichen ScreenFlip warten zu müssen, da dieser Threadgesteuert wäre.

Weiß jemand für so etwas eine Lösung, fals dies in PB ohne größere Probleme realisierbar ist?

Oder fungiert sogar FlipBuffers(2) nach diesem Prinzip?

Verfasst: 16.03.2006 20:45
von Stefan
So sollten die Sprite-Befehle eigentlich auch im MT-modus funktioniren:

Code: Alles auswählen


Procedure _PB_DDrawBase()
!extrn _PB_DDrawBase
!MOV EAX,[_PB_DDrawBase]
ProcedureReturn
EndProcedure

;Procedure _PB_Screen_Windowed()
;!extrn _PB_Screen_Windowed 
;!MOV EAX,[_PB_Screen_Windowed]
;ProcedureReturn
;EndProcedure

#DDSCL_EXCLUSIVE=16
#DDSCL_FULLSCREEN=1
#DDSCL_MULTITHREADED=1024
#DDSCL_NORMAL=8

Global UseDX7Mutex.l

Procedure MTLockDX7Mutex()
LockMutex(UseDX7Mutex)
EndProcedure

Procedure MTUnLockDX7Mutex()
UnlockMutex(UseDX7Mutex)
EndProcedure

Procedure MTOpenWindowedScreen(hWnd,x,y,width,height,AutoStretch,ROffset,BOffset)
Result=OpenWindowedScreen(hWnd,x,y,width,height,AutoStretch,ROffset,BOffset)
If Result=0:ProcedureReturn 0:EndIf
UseDX7Mutex=CreateMutex()
*DD.IDirectDraw7=_PB_DDrawBase()
;*DD\SetCooperativeLevel(ScreenID(),#DDSCL_EXCLUSIVE|#DDSCL_FULLSCREEN|#DDSCL_MULTITHREADED)  ; Fullscreen
*DD\SetCooperativeLevel(ScreenID(),#DDSCL_NORMAL|#DDSCL_MULTITHREADED)
ProcedureReturn Result
EndProcedure

Procedure MTClearScreen(Color)
LockMutex(UseDX7Mutex)
Result=ClearScreen(Color)
UnlockMutex(UseDX7Mutex)
ProcedureReturn Result
EndProcedure

Procedure MTFlipBuffers(Flags)
LockMutex(UseDX7Mutex)
Result=FlipBuffers(Flags)
UnlockMutex(UseDX7Mutex)
ProcedureReturn Result
EndProcedure




Procedure MyRepaint(dummy)
Repeat
MTFlipBuffers(0)
Delay(15)
ForEver
EndProcedure


InitSprite()
OpenWindow(1,0,0,320,240,"TEST")
MTOpenWindowedScreen(WindowID(1),0,0,320,240,0,0,0)

CreateSprite(1,100,100)

StartDrawing(SpriteOutput(1))
Circle(100,100,100,#Red)
StopDrawing()


TRepaint=CreateThread(@MyRepaint(),0)
Repeat

Delay(50)

MTLockDX7Mutex()
ClearScreen(RGB(255,0,255))
RandomSeed(100)
For C=0 To 100
DisplaySprite(1,Random(200),Random(200))
Next
MTUnLockDX7Mutex()

Until WindowEvent()=#PB_Event_CloseWindow
KillThread(TRepaint)

Verfasst: 16.03.2006 21:51
von KTX82
Wow, Danke, das wäre schon mal die Lösung für Threads, jetzt fehlt nur noch etwas für einen 3. Screenbuffer, das auch wirklich nur fertig gerenderte Bilder in den Frontbuffer kommen. Ich meine da mal was gelesen zu haben, kann mich auch irren... werde nochmal suchen.
Aber vielen Dank @Stefan :allright:

Code: Alles auswählen

;
;                  Thread
;                  +------------------------------------+
; Hauptschleife    |                                    |
; +----------------+---------------+                    |
; | Zeichnen       | Fertiges Bild |                    |
; |                |               |                    |
; |    |           |               | -> FrontBuffer (3) |
; |                |               |                    |
; | Buffer 1   ->  |   Buffer 2    |                    |
; +----------------+---------------+                    |
;                  |                                    |
;                  +------------------------------------+
;
;
; Buffer 1: Hier wird nur gezeichnet
; Buffer 2: Bekommt von der Hauptschleife nach fertig zeichnen das fertig gerenderte Bild
; Buffer 3: Der Thread holt aus dem Buffer 2 das fertige Bild in den Buffer 3 (Monitorbild)

Verfasst: 16.03.2006 21:54
von Stefan
Zu was brauchst du 3 Buffer, du kannst das Mutex doch auch solange sperren, bis alles dargestellt wurde ?

Verfasst: 16.03.2006 22:10
von KTX82
Das die Hauptschleife nicht auf FlipBuffers warten muss, da dieses ja immer auf den Sync wartet. Und da Sync schon nicht fehlen sollte, braucht man einen dritten Buffer aus dem unabhängig von der Hauptschleife ein Thread immer das FlipBuffers (in diesem Fall muss es ein eigener Befehl werden) ausführt.
Ich glaube das nennt man Tripplebuffering /:-> http://de.wikipedia.org/wiki/Tripplebuffering