FlipBuffers() ... ein Resourcenfresser ???

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
PureLust
Beiträge: 1145
Registriert: 21.07.2005 00:02
Computerausstattung: Hab aktuell im Grunde nur noch 'nen Lenovo Yoga 2 Pro im Einsatz.
Wohnort: am schönen Niederrhein

FlipBuffers() ... ein Resourcenfresser ???

Beitrag von PureLust »

Hallo zusammen, ...

könnte es sein, dass FlipBuffers() beim Warten auf den Bildschirmsync nicht resourcenschonend wartet und die Kontrolle solange abgibt, sonden zu 100% die CPU auslastet ??? :shock:

Ist natürlich eine nicht besonders schöne Art und Weise ... /:->

Gibt es evtl. irgenwie eine andere Möglichkeit den Sync abzufangen (evtl. über Interrupts oder über 'nen Event)?

Oder gibt es vielleicht eine Möglichkeit die aktuelle Rasterzeile abzufragen?
So könnte man nach dem Zeichnen evtl. einen Delay() einbauen, der kurz vor dem Sync zu ende ist und anschließend einen FlipBuffers(1) machen.

Siehe CPU Belastung mit und ohne Delay() bei gleicher Framerate im Beispiel:

Code: Alles auswählen

InitSprite()
InitKeyboard()

StartTimer = ElapsedMilliseconds()-1
FrameCounter.l = 0
If OpenWindow(1,100,100,320,240,0,"jhg")
   If OpenWindowedScreen(WindowID(1),0,0,320, 240, 16,0,0)
      StartTimer = ElapsedMilliseconds()-1
      Repeat
         FrameCounter + 1
         StartDrawing(ScreenOutput()) 
         DrawText("   FPS : "+Str(FrameCounter *1000 / (ElapsedMilliseconds() - StartTimer))+"    ")
         StopDrawing() 
         ;Angenommen mann könnte die aktuelle Rasterzeile auslesen,
         ;so könnte man die Zeit bis zum nächsten Sync berechnen und durch
         ;einen entsprechenden Delay() auffüllen, ohne die Framerate zu beeinflussen.
         Delay(8)    ; ohne Delay() ist die CPU-Belastung durch FlipBuffers() = 100%
         FlipBuffers(1)
         ExamineKeyboard()
      Until KeyboardReleased(#PB_Key_Escape) 
   EndIf
EndIf
End
Thanks und Greetz, Luke.
Zuletzt geändert von PureLust am 09.10.2005 16:20, insgesamt 2-mal geändert.
[Dynamic-Dialogs] - komplexe dynamische GUIs einfach erstellen
[DeFlicker] - Fenster flimmerfrei resizen
[WinFX] - Window Effekte (inkl. 'durchklickbares' Window)
Benutzeravatar
MLK
Beiträge: 267
Registriert: 01.11.2004 13:17
Wohnort: Hamburg

Beitrag von MLK »

interessant dass du FlipBuffer() beschuldigst. es liegt aber wohl eher an der schleife an sich.

Code: Alles auswählen

Repeat
Until GetAsyncKeyState_(#VK_RETURN)
ein Delay(1 oder 3 oder ...) ist bei einer hauptschleife mit FlipBuffers() standard mit d.
Benutzeravatar
PureLust
Beiträge: 1145
Registriert: 21.07.2005 00:02
Computerausstattung: Hab aktuell im Grunde nur noch 'nen Lenovo Yoga 2 Pro im Einsatz.
Wohnort: am schönen Niederrhein

Beitrag von PureLust »

Hi MLK, ...

an der Schleife lag as nicht, da KeyboardReleased() ja ohnehin nur nach jedem Sync ausgeführt wird, kann es auch nicht solche Auswirkungen haben.

Ich kreise das Problem deswegen bei FlipBuffers() ein, weil er ja bis zum nächsten Sync schlicht und ergreifend nur WARTEN soll, was er ja auch tut - dies jedoch anscheinend durch eine Dauerschleife macht und sich eben nicht unbedingt multitasking- und resourcenfreundlich verhält.

Irgendwie wird FlipBuffers() ja an die Sync-Informationen heran kommen und auswerten.
Leider scheint er danach die Wartezeit nun mal sinnlos in einer Dauerschleife zu verbringen.

Wenn man also ebenfalls an diese Infos herankommen könnte, so wäre es denkbar, einen Ersatz für FlipBuffers zu schreiben, bei der die Wartezeit halt eben nicht sinnlos 'verbraten' wird.

Und es macht AFAIK schon einen Unterschied ob man die Kontrolle an das OS für 1ms oder für 10ms abgibt. Somit wäre eine exakte Berechnung der optimalen Delay()-Zeit schon resourceschonender als pauschal ein Delay(1) zu machen.

In diesem Sinne, ... Greetze, Luke.
[Dynamic-Dialogs] - komplexe dynamische GUIs einfach erstellen
[DeFlicker] - Fenster flimmerfrei resizen
[WinFX] - Window Effekte (inkl. 'durchklickbares' Window)
glubschi90
Beiträge: 274
Registriert: 04.09.2004 01:43
Wohnort: Würzburg

Beitrag von glubschi90 »

Ich würde sagen, dass FlipBuffers()deshalb soviel CPU-Auslastung benötigt, weil der Befehl ja nicht nur dazu da ist, die Framerate zu regulieren, sondern auch den Backbuffer mit dem FrontBuffer und umgekehrt vertauscht.
Das braucht natürlich mehr Leistung, als nur eine Wartefunktion.
PureBasic 4.30
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Beitrag von Danilo »

PureLust hat geschrieben:Ich kreise das Problem deswegen bei FlipBuffers() ein, weil er ja bis zum nächsten Sync schlicht und ergreifend nur WARTEN soll, was er ja auch tut - dies jedoch anscheinend durch eine Dauerschleife macht und sich eben nicht unbedingt multitasking- und resourcenfreundlich verhält.
FlipBuffers(1) ruft intern auch nur IDirectDrawSurface7::Flip()
mit dem Parameter DDFLIP_WAIT auf. Damit wird der Flip
synchronisiert und DirectX kehrt erst zurück wenn der Flip
durchgeführt wurde. Das heißt nicht PB wartet hier, sondern
DirectX.

Die Scanline kannste mit IDirectDraw7::GetScanLine() bekommen,
falls Du Dir da selbst was basteln willst.

Eine Überlegung wäre vielleicht:

Code: Alles auswählen

While IDirectDrawSurface7::GetFlipStatus(#DDGFS_CANFLIP) <> #DD_OK
  Delay(1)
Wend
IDirectDrawSurface7::Flip(...)
Oder:

Code: Alles auswählen

IDirectDrawSurface7::Flip(0, DDFLIP_DONOTWAIT)
While IDirectDrawSurface7::GetFlipStatus(#DDGFS_ISFLIPDONE) <> #DD_OK
  Delay(1)
Wend
Das loopt solange bis der Flip ausgeführt ist. Auf die Errors
wie DDERR_SURFACELOST usw. muß man dabei natürlich
noch checken, es zeigt aber das Prinzip wie es gehen könnte.

1 Millisekunde ist eine ziemlich lange Zeit. Aber oftmals wird
Delay() nicht so schnell zurück kommen, wenn es zu einem
anderen Prozess switcht der auch bissl Power zieht.
D.h. Du hättest dann evtl. einen Delay von vielleicht 5ms,
was einfach zu lange ist. Delay/Sleep gibt ja nur an das Du
mindestens diese Zeit warten willst, garantiert aber nicht das
es auch nur maximal soviel Zeit ist.
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
Benutzeravatar
PureLust
Beiträge: 1145
Registriert: 21.07.2005 00:02
Computerausstattung: Hab aktuell im Grunde nur noch 'nen Lenovo Yoga 2 Pro im Einsatz.
Wohnort: am schönen Niederrhein

Beitrag von PureLust »

Hi Danilo, ...

vielen Dank, das ist genau was ich gesucht hatte !!! :allright:
Und auch die Problematik mit dem 'nicht rechtzeitig zurück kommenden' Delay() hast Du natürlich richtig gesehen.

Jetzt hab ich nur noch ein Problem:
Ich kann leider mit Deinen Beispielen, oder besser gesagt mit IDirectDrawSurface7::GetFlipStatus(#DDGFS_CANFLIP) nix anfangen.

GetFlipStatus() wird von der IDE nicht erkannt.
Fehlt mir irgend eine Lib oder benötige ich dazu einen Include???

BTW: Wollte mich nochmal für Deine PM vom Juli bedanken !!!
Wie Du siehst bin ich letztendlich doch bei Pure gelandet !!! ;)


ThanX & Gruß, Luke
[Dynamic-Dialogs] - komplexe dynamische GUIs einfach erstellen
[DeFlicker] - Fenster flimmerfrei resizen
[WinFX] - Window Effekte (inkl. 'durchklickbares' Window)
Benutzeravatar
AndyX
Beiträge: 1272
Registriert: 17.12.2004 20:10
Wohnort: Niederösterreich
Kontaktdaten:

Beitrag von AndyX »

btw: StartDrawing() etc und Plot() ohne Farbparameter ist auch n Speedbremser...
Benutzeravatar
Danilo
-= Anfänger =-
Beiträge: 2284
Registriert: 29.08.2004 03:07

Beitrag von Danilo »

PureLust hat geschrieben:Jetzt hab ich nur noch ein Problem:
Ich kann leider mit Deinen Beispielen, oder besser gesagt mit IDirectDrawSurface7::GetFlipStatus(#DDGFS_CANFLIP) nix anfangen.

GetFlipStatus() wird von der IDE nicht erkannt.
Fehlt mir irgend eine Lib oder benötige ich dazu einen Include???
Das war nur Pseudo-Code für die DX-Interfaces.

Hab mal ein FlipBuffers_(sync) gemacht:

Code: Alles auswählen

;
; Danilo, 09.10.2005
;
Procedure FlipBuffers_(sync)
  #DDFLIP_WAIT       = $1
  #DDFLIP_NOVSYNC    = $8
  #DDFLIP_DONOTWAIT  = $20
  #DD_OK             = 0
  #DDGFS_ISFLIPDONE  = $00000002
  Shared FlipBuffers_Shared_DDS_Front.IDirectDrawSurface7
  !extrn _PB_DirectX_PrimaryBuffer
  !PUSH  dword [_PB_DirectX_PrimaryBuffer]
  !POP   dword [v_FlipBuffers_Shared_DDS_Front]
  
  If sync
     sync = #DDFLIP_WAIT
  Else
     sync = #DDFLIP_NOVSYNC
  EndIf
  
  hRet = FlipBuffers_Shared_DDS_Front\Flip(0, sync)
  ;If hRet = #DDERR_SURFACELOST
  ;   FlipBuffers_Shared_DDS_Front\Restore()
  ;EndIf

  If sync <> #DDFLIP_NOVSYNC
    Delay(1)
  EndIf

  While FlipBuffers_Shared_DDS_Front\GetFlipStatus(#DDGFS_ISFLIPDONE) <> #DD_OK
    Delay(1)
  Wend
  InvalidateRect_(ScreenID(),0,0)
  UpdateWindow_(ScreenID())  
EndProcedure


If InitSprite()=0 Or InitKeyboard()=0
  MessageRequester("ERROR","Cant init DirectX !",0):End
EndIf


If OpenWindow(1,100,100,320,240,#PB_Window_SystemMenu,"jhg")
  If OpenWindowedScreen(WindowID(1),0,0,320,240,1,0,0)
    If CreateSprite(1,32,32)=0
      End
    Else
      If StartDrawing(SpriteOutput(1))
        Box(0,0,32,32,RGB($00,$00,$FF))
        StopDrawing()
      EndIf
    EndIf
    StartTimer   = ElapsedMilliseconds()
    Repeat
      time = ElapsedMilliseconds()
      If time >= StartTimer+1000
        StartTimer   = time
        FPS          = FrameCounter
        FrameCounter = 0
      Else
        FrameCounter + 1
      EndIf

      ClearScreen(0,0,0)

      If StartDrawing(ScreenOutput())
        DrawingMode(1)
        FrontColor($FF,$FF,$00)
        DrawText(Str(FPS))
        Circle(160,120,x,$FFFFFF)
        x-1
        If x = -1: x = 120:EndIf
        StopDrawing()
      EndIf
      
      y+1
      DisplaySprite(1,160-16,y)
      If y>=240+32:y=-32:EndIf

      FlipBuffers_(1)
      ExamineKeyboard()
      If WindowEvent() = #PB_Event_CloseWindow
        quit = 1
      EndIf
    Until KeyboardReleased(#PB_Key_Escape) Or quit
  EndIf
EndIf
Bei FlipBuffers_(1) bekomme ich hier 64 FPS, bei FlipBuffers_(0)
sind es etwas über 400 FPS.
Beim PB-FlipBuffers(0) synchronisiert es bei mir hier trotzdem,
d.h. ich bekomme da auch nur ~60FPS und nicht 400 wie bei
meinem FlipBuffers_(0)

Mit Synchronisation ist die CPU-Auslastung hier 0%.

Irgendwie wundert mich das alles jetzt etwas. Ich weiß nicht
ob das PB-FlipBuffers noch irgend etwas anderes macht.
Wenn es so einfach ist wie in meinem Code, dann verstehe ich
jetzt auch nicht ganz wieso es bei PB soviel CPU-Auslastung hat.
Irgendwas ist da doch faul... hmm.

BTW: Wenn Du mit WindowedScreens arbeitest muß unbedingt
ein WindowEvent() mit in die Schleife, sonst sammeln sich die
Nachrichten in der Queue, bis es zum Überlauf kommt.
Zuletzt geändert von Danilo am 09.10.2005 19:41, insgesamt 1-mal geändert.
cya,
...Danilo
"Ein Genie besteht zu 10% aus Inspiration und zu 90% aus Transpiration" - Max Planck
Benutzeravatar
Andre
PureBasic Team
Beiträge: 1765
Registriert: 11.09.2004 16:35
Computerausstattung: MacBook Core2Duo mit MacOS 10.6.8
Lenovo Y50 i7 mit Windows 10
Wohnort: Saxony / Deutscheinsiedel
Kontaktdaten:

Beitrag von Andre »

Habe Fred mal gebeten, sich das hier beschriebene Problem näher anzusehen. 8)
Bye,
...André
(PureBasicTeam::Docs - PureArea.net | Bestellen:: PureBasic | PureVisionXP)
Benutzeravatar
PureLust
Beiträge: 1145
Registriert: 21.07.2005 00:02
Computerausstattung: Hab aktuell im Grunde nur noch 'nen Lenovo Yoga 2 Pro im Einsatz.
Wohnort: am schönen Niederrhein

Beitrag von PureLust »

@Danilo:
Danilo hat geschrieben:Bei FlipBuffers_(1) bekomme ich hier 64 FPS, bei FlipBuffers_(0)
sind es etwas über 400 FPS.
Beim PB-FlipBuffers(0) synchronisiert es bei mir hier trotzdem,
d.h. ich bekomme da auch nur ~60FPS und nicht 400 wie bei
meinem FlipBuffers_(0)
Hmmm ... das ist scheinbar wohl eine Eigenart von Windowed-Screens. :roll:

Bei Windowed-Screens syncronisiert mir PB-FlipBuffer() ebenfalls IMMER auf 60FPS bei 100% CPU-Last.
Bei FullScreens auf 60 bzw. garnicht (ca. 4900FPS) bei ebenfalls 100% CPU-Last.

Bei Deinem FlipBuffers_ erhalte ich bei mir im Windowed-Screen Modus 99FPS bei 0% CPU-Last bzw. ~2250FPS bei 100% CPU-Last.
Im FullScreen Modus erhalte ich hingegen die korrekten 60FPS bei ~40% bzw. ~4450FPS bei 100%.

Ich hatte mich natürlich gefragt, wo die 99FPS im Windowed-Screen Modus herkommen.
Nach einigem Rumprobieren habe ich dann festgestellt, dass ich durch das origianl PB-FlipBuffers(0) mit einem Delay(1) im FullScreen Modus die gleichen Werte erhalte (also 99FPS und 0% Auslastung).
Mit gleichen Parametern erhalte ich im Windowed-Screenmode jedoch die besagten 60FPS mit ~40% CPU Last - also die gleichen Werte wie bei Dir im FullScreen Mode.

Also alles in allem wohl ein recht undurchsichtiges bzw. verdrehtes Verhalten. /:->

PS: Hab ich Deine Routine richtig verstanden, dass sie im Grunde effektiv nichts weiter macht als ein Delay(1) einzufügen wenn (1) als Parameter übergeben wird (mal abgesehen davon, dass sie darauf warten würde, wenn der Flip noch nicht vollzogen ist: FlipBuffers_Shared_DDS_Front\GetFlipStatus(#DDGFS_ISFLIPDONE) <> #DD_OK)?
[Dynamic-Dialogs] - komplexe dynamische GUIs einfach erstellen
[DeFlicker] - Fenster flimmerfrei resizen
[WinFX] - Window Effekte (inkl. 'durchklickbares' Window)
Antworten