Bei meinem Projekt dreht sich alles um schnelle und geschickte 3D-Stifteingabe mit bis zu 200 Eingabepunkten pro Sekunde.
Software Design Frage: Reicht die Ausgabegeschwindigkeit um jedes Frame ausgeben oder muß ein Fokus auf bestimmte Bildschirmbereiche gelegt werden?
Beim Test der Bildschirmausgabe habe ich einen starken Geschwindigkeitseinbruch bei OpenWindow, OpenWindowedScreen gegenüber OpenScreen.
Sind die Parameter für OpenWindow und OpenWindowedScreen richtig gesetzt um die Hardware-Beschleunigung zu erreichen?
Oder gibt es einen Weg die Adressen und die Schreibrechte vom Videospeicher nach OpenWindowedScreen zu bekommen?
Code: Alles auswählen
; Warum Geschwindigkeits-Test: Schreibe auf den Bildschirm-Buffer hier mit OpenWindowedScreen. Werden mehr als 59 fps erreicht?
; Erstellt mit PureBasic 5.51 (x64) auf Wacom Cintiq Companion 2 2560x1440xR8G8B8A8@59 Windows 8.1
; 78619 Zeilen/s 54 fps 98-102% CPU-Auslastung laut Resourcenmanager
; bei reduzierter Auflösung 1920x1080 111380 Zeilen/s 77 fps
; offen Stimmen die Aufrufe von OpenWindow und OpenWindowedScreen zur Hardware-Beschleunigung, da nur 21% der OpenScreen Leistung? (Win 8.1 und 7 Pro SP1 aber nicht Vista Home SP2)
; Oder gibt es einen Weg die Adressen und die Schreibrechte vom Videospeicher nach OpenWindowedScreen zu bekommen?
EnableExplicit
Declare zeile(*wert) ; Procedure gibt Zeilen auf den Bildschirm aus.
Structure Bildschirmtyp : Name.s : Xpixel.w : Ypixel.w : Tiefe.w : fps.f : *Buffer : *Buffer2 : Pitch.l : Pixelformat.w : EndStructure
Dim Bildschirme.Bildschirmtyp(0) ; Im diesem Beispiel gibt es nur einen Bildschirm mit der Nummer 0
InitSprite(): ExamineScreenModes()
ExamineDesktops()
Bildschirme(0)\Xpixel=DesktopWidth(0) : Bildschirme(0)\Ypixel=DesktopHeight(0): Bildschirme(0)\fps=DesktopFrequency(0)
Define Fenster=OpenWindow(#PB_Any,
0, ; Anfängliche x Position des Fensters
0, ; Anfängliche y Position des Fensters
Bildschirme(0)\Xpixel , ; 2560 Pixel Breite
Bildschirme(0)\Ypixel, ; 1440 Pixel Höhe
"Geschwindigkeits-TEST", ; Fenstername
#PB_Window_BorderLess|#PB_Window_NoGadgets) ; Flags keine Ränder - hier könnte etwas fehlen.
; kein ParentWindow
If 0=Fenster : MessageRequester("Fataler Fehler","OpenWindow fehlgeschlagen!") :End :EndIf
If 0=OpenWindowedScreen(WindowID(Fenster),
0, ; x Position 0 links
0, ; y Position 0 oben
Bildschirme(0)\Xpixel, ; 2560 Pixel Breite
Bildschirme(0)\Ypixel, ; 1440 Pixel Höhe
#False, ; keine Anpassung der Größe
0, ; Stetuszeile RightOffset
0, ; Statuszeile BottomOffset
#PB_Screen_SmartSynchronization) ; FlipModus - Es scheint nur ein Videobuffer erstellt zu werden.
MessageRequester("Fataler Fehler ","OpenWindowScreen fehlgeschlagen!")
End
EndIf
StartDrawing(ScreenOutput()) :
Bildschirme(0)\Buffer = DrawingBuffer() ; Finde die Adresse des Bildschirmm
Bildschirme(0)\Pitch=DrawingBufferPitch()
Bildschirme(0)\Pixelformat=DrawingBufferPixelFormat()
StopDrawing()
FlipBuffers()
StartDrawing(ScreenOutput()) : Bildschirme(0)\Buffer2 = DrawingBuffer() :StopDrawing()
Define j=0
Define i
Dim *Pufferfeld(Bildschirme(0)\Ypixel)
*Pufferfeld(0)=AllocateMemory(Bildschirme(0)\Pitch * Bildschirme(0)\Ypixel)
Define *ptr=*Pufferfeld(0)
For i=0 To Bildschirme(0)\Ypixel-1 ; Für Jede Zeile des *Pufferfeld
*Pufferfeld(i) = *ptr
*ptr+Bildschirme(0)\Pitch
; Füllte die Zeile mit grünen Punkten unterschiedlicher Helligkeit
For j=0 To Bildschirme(0)\Pitch-4 Step 4 : PokeL(*Pufferfeld(i)+j,RGBA(0,Random(255),0,0)) : Next j
Next i
Define fertig=#False
Define fliptime=ElapsedMilliseconds()+16
Define Zeilen=0
Define Cpus=CountCPUs(#PB_System_ProcessCPUs) :Dim thread(Cpus-1)
thread(0)=CreateThread(@Zeile(),i) : ThreadPriority(thread(0),17) ; Prio 31 kaum Wirkung
thread(1)=CreateThread(@Zeile(),i) : ThreadPriority(thread(1),17) ; 2. Thread bringt 10 zusätzliche fps
; DisableDebugger ; bringt kaum etwas
Define Startzeit=ElapsedMilliseconds()
Repeat
Repeat
Define Event = WindowEvent() ; Windows Event-Abfrage auf ALT-F4
If Event = #PB_Event_CloseWindow : fertig=#True : EndIf
Until Event = 0
If ElapsedMilliseconds()>=fliptime ; Nach 16 ms wird ein FlipBuffers ausgelöst
FlipBuffers()
fliptime=ElapsedMilliseconds()+16
Else
Delay(1) ; Warte 1 Millisekunde - das Betriebssystems kann sich um die Threads und um anders kümmern
EndIf
Until fertig=#True
EnableDebugger
For i=0 To Cpus-1 : If thread(i)<>0 : KillThread(thread(i)) : EndIf : Next i ; Threads beenden.
Define Zeit.f=(ElapsedMilliseconds()-Startzeit)/1000 ; Messung ausgeben
Define ZeilenProSekunde=Zeilen/Zeit
MessageRequester("Messung",
StrF(Zeit)+" s Zeilen:"+Str(Zeilen)+" Zeilen/s:"+Str(ZeilenProSekunde)+" fps:"+Str(ZeilenProSekunde/1440)+
" "+Bildschirme(0)\Xpixel+"x"+Bildschirme(0)\Ypixel+"@"+Bildschirme(0)\fps+#CRLF$+
Hex(Bildschirme(0)\Buffer)+" "+Hex(Bildschirme(0)\Buffer2))
End
; Thread zur Ausgabe von Zeilen auf dem Bildschirm-Buffer
Procedure zeile(*wert)
Shared Zeilen
Shared *Pufferfeld()
Shared Bildschirme()
Define addzeilen=1 ; Es wird eine Bildschirmzeile ausgegeben
Define Laenge=Bildschirme(0)\Pitch*addzeilen ; Bildschirmzeilen in Bytes
Repeat
Define *Ziel= Bildschirme(0)\Buffer+Random( Bildschirme(0)\Ypixel-addzeilen) * Bildschirme(0)\Pitch ; zufällige Zeile
Define *Quelle = *Pufferfeld(Random(Bildschirme(0)\Ypixel-addzeilen)) ; zufällige Zeile
CopyMemory(*Quelle,*Ziel,Laenge) ; hier wird die CPU-Zeit verbraucht
; DisableDebugger:EnableASM:Mov rcx,Laenge : Sar rcx,3 : mov rsi, *Quelle : mov rdi, *Ziel : rep movsq :DisableASM:EnableDebugger
; x64 nötig - keine Wirkung
Zeilen+addzeilen ; Könnte ein Datarace sein?
ForEver
EndProcedure
; Geschichte 170101 Es sollte grünes Pixelrasuchen zu sehen sein, vergleichbar TV-Rauschen ohne Empfang.
Code: Alles auswählen
; Warum Geschwindigkeits-Test: Schreibe auf den Bildschirm-Buffer hier mit OpenScreen. Werden mehr als 59 fps erreicht?
; Erstellt mit PureBasic 5.51 (x64) auf Wacom Cintiq Companion 2 2560x1440xR8G8B8A8@59 Windows 8.1
; Zeilen/s:379696 fps:263
EnableExplicit
Declare zeile(*wert) ; Procedure gibt Zeilen auf den Bildschirm aus.
Structure Bildschirmtyp : Name.s : Xpixel.w : Ypixel.w : Tiefe.w : fps.f : *Buffer : *Buffer2 : Pitch.l : Pixelformat.w : EndStructure
Dim Bildschirme.Bildschirmtyp(0) ; Im diesem Beispiel gibt es nur einen Bildschirm mit der Nummer 0
InitSprite(): ExamineScreenModes()
ExamineDesktops()
Bildschirme(0)\Xpixel=DesktopWidth(0) : Bildschirme(0)\Ypixel=DesktopHeight(0): Bildschirme(0)\fps=DesktopFrequency(0)
InitKeyboard()
Define main_whnd=OpenScreen(Bildschirme(0)\Xpixel,
Bildschirme(0)\Ypixel,
32, ; Bildschirme(0)\Tiefe,
"Geschwindigkeits-TEST",
#PB_Screen_SmartSynchronization)
StartDrawing(ScreenOutput()) :
Bildschirme(0)\Buffer = DrawingBuffer() ; Finde die Adresse des Bildschirmm
Bildschirme(0)\Pitch=DrawingBufferPitch()
Bildschirme(0)\Pixelformat=DrawingBufferPixelFormat()
StopDrawing() :FlipBuffers()
StartDrawing(ScreenOutput()) : Bildschirme(0)\Buffer2 = DrawingBuffer() ; Finde die 2, Adresse des Bildschirmm
Define j=0
Define i
Dim *Pufferfeld(Bildschirme(0)\Ypixel)
*Pufferfeld(0)=AllocateMemory(Bildschirme(0)\Pitch * Bildschirme(0)\Ypixel)
Define *ptr=*Pufferfeld(0)
For i=0 To Bildschirme(0)\Ypixel-1 ; Für Jede Zeile des *Pufferfeld
*Pufferfeld(i) = *ptr
*ptr+Bildschirme(0)\Pitch
; Füllte die Zeile mit grünen Punkten unterschiedlicher Helligkeit
For j=0 To Bildschirme(0)\Pitch-4 Step 4 : PokeL(*Pufferfeld(i)+j,RGBA(0,Random(255),0,0)) : Next j
Next i
Define fertig=#False
Define fliptime=ElapsedMilliseconds()+16
Define Zeilen=0
Define Cpus=CountCPUs(#PB_System_ProcessCPUs) :Dim thread(Cpus-1)
thread(0)=CreateThread(@Zeile(),i) : ThreadPriority(thread(0),17) ; alleine Zeilen/s:347098 fps:241
thread(1)=CreateThread(@Zeile(),i) : ThreadPriority(thread(1),17)
; DisableDebugger ; bringt kaum etwas
Define Startzeit=ElapsedMilliseconds()
Repeat
ExamineKeyboard() ; Prüfe Tasteneingaben ESC-Taste beendet Programm
Until KeyboardPushed(#PB_Key_Escape) ;
EnableDebugger
For i=0 To Cpus-1 : If thread(i)<>0 : KillThread(thread(i)) : EndIf : Next i ; Threads beenden.
CloseScreen()
Define Zeit.f=(ElapsedMilliseconds()-Startzeit)/1000 ; Messung ausgeben
Define ZeilenProSekunde=Zeilen/Zeit
Debug StrF(Zeit)+" s Zeilen:"+Str(Zeilen)+" Zeilen/s:"+Str(ZeilenProSekunde)+" fps:"+Str(ZeilenProSekunde/1440)+
" "+Bildschirme(0)\Xpixel+"x"+Bildschirme(0)\Ypixel+"@"+Bildschirme(0)\fps+#CRLF$+
Hex(Bildschirme(0)\Buffer)+" "+Hex(Bildschirme(0)\Buffer2)
End
; Thread zur Ausgabe von Zeilen auf dem Bildschirm-Buffer
Procedure zeile(*wert)
Shared Zeilen
Shared *Pufferfeld()
Shared Bildschirme()
Define addzeilen=1
Define Laenge=Bildschirme(0)\Pitch*addzeilen
Repeat
Define *Ziel= Bildschirme(0)\Buffer+Random( Bildschirme(0)\Ypixel-addzeilen) * Bildschirme(0)\Pitch
Define *Quelle = *Pufferfeld(Random(Bildschirme(0)\Ypixel-addzeilen))
CopyMemory(*Quelle,*Ziel,Laenge)
; EnableASM : Mov rcx,Laenge : Sar rcx,3 : mov rsi, *Quelle : mov rdi, *Ziel : rep movsq : DisableASM ; x64 nötig - kaum Wirkung
Zeilen+addzeilen
ForEver
EndProcedure