Bildschirmsynchronisierung
Übersicht

![]() |
hecticSieger des IS Talentwettbewerb 2006Betreff: Bildschirmsynchronisierung |
![]() Antworten mit Zitat ![]() |
---|---|---|
Das alte Leid mit der Asynchronität zwischen Grafikkarte und der Bildschirmausgabe. Selbstverständlich gibt es dafür eine sehr einfache Lösung, indem das VWait![]() ![]() Also was als Alternative nutzen? Ein Hauptproblem ist wie ich finde, dass Waittimer ![]() Habe ich durch sehr viel Kleinarbeit selbst herausgefunden. Hier mal die Formel: Code: [AUSKLAPPEN] FPS=58
Print FPS+" wird zu "+(1000.0/(1000/(FPS)))+" FPS" Print "Ergibt "+((1000.0/(1000/(FPS)))-60)+" Ruckler pro Sekunde" Also, was kann man noch machen? Habe dazu nun so einiges rumprobiert. Mit ScanLine ![]() Also nun eine neue Idee. Man nehme den Wert von ScanLine() und je nach Position werden alle Objekte auf dem Bildschirm nach vorne oder nach hinten gezogen. Kommt es nun zu einem Bruch, so wurden ja die Objekte ja schon vorraus oder nach gezogen und. So ähnlich wie man es bei frameunabhängigem Programmieren macht. Tatsächlich ist die Bewegung auf dem Blatt zukelig, wegen der Asynchronität aber optisch deutlich besser. Es gilt nun nur noch, den Zeitpunk des Bruchs so genau wie möglich vorraus zu berechnen. Denn eine Reaktion auf den echten Wert ist bereits zu spät. Hier mal mein erster Prototyp mit eingestellten 60 FPS: B3D Code: [AUSKLAPPEN] Graphics3D 1920,1080,0,2
SetBuffer BackBuffer() Local timer=CreateTimer(60) Local camera=CreateCamera() PositionEntity camera,0,0,-45 Local cube[4] cube[0]=CreateCube():ScaleEntity cube[0],1,10,1 cube[1]=CreateCube():ScaleEntity cube[1],1,10,1 cube[2]=CreateCube():ScaleEntity cube[2],1,10,1 cube[3]=CreateCube():ScaleEntity cube[3],1,10,1 cube[4]=CreateCube():ScaleEntity cube[4],1,10,1 Local scan_line#=0 Local scan_max#=1 Local scan_offset#=1 Local scan_distance#=1 Local rotate%=0 Local value%=-86 While Not KeyHit(1) rotate=(rotate Mod 20)+1 PositionEntity cube[0],rotate-50+scan_offset*(value*0.01),0,0 PositionEntity cube[1],rotate-30+scan_offset*(value*0.01),0,0 PositionEntity cube[2],rotate-10+scan_offset*(value*0.01),0,0 PositionEntity cube[3],rotate+10+scan_offset*(value*0.01),0,0 PositionEntity cube[4],rotate+30+scan_offset*(value*0.01),0,0 If KeyDown(203) Then value=value-1 If KeyDown(205) Then value=value+1 RenderWorld WaitTimer timer Text 20,20,value Text 20,40,"Nicht zu lange hier rein schauen, sonst wird euch schlecht davon. Ernsthaft" scan_distance=scan_max/60 scan_line=ScanLine()-scan_distance If scan_line<0 Then scan_line=scan_max If scan_line>scan_max Then scan_max=scan_line scan_offset=scan_line/scan_max Flip 0:Cls Wend Funktioniert allerdings nur im Fenstermodus gut. Im Vollbild geht der Vorteil so gegen nahezu Null. Kann natürlich auch sein, dass jeder Bildschirm seine eigenen Werte benötigt. Mich würde wirklich mal interessieren, ob sich sonst noch jemand damit beschäftigt hat und zu welchen Lösungen oder Fehlschlägen es gekommen ist. |
||
Download der Draw3D2 V.1.1 für schnelle Echtzeiteffekte über Blitz3D |
![]() |
HolzchopfMeisterpacker |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ich habe mich ehrlich gesagt bis jetzt nie so wirklich damit auseinander gesetzt ![]() Folgender Code läuft bei mir ganz gut: BlitzBasic: [AUSKLAPPEN] Const WIDTH = 1920 Oder in BlitzMax: [AUSKLAPPEN] SuperStrict Beide erzielen nicht hochglänzende Ergebnisse in Sachen CPU-Last. Aber das bisschen wird man ertragen können, wenn die Ästhetik so wichtig ist. mfG Holzchopf |
||
Erledige alles Schritt um Schritt - erledige alles. - Holzchopf
CC BY ♫ BinaryBorn - Yogurt ♫ (31.10.2018) Im Kopf da knackt's und knistert's sturm - 's ist kein Gedanke, nur ein Wurm |
![]() |
hecticSieger des IS Talentwettbewerb 2006 |
![]() Antworten mit Zitat ![]() |
---|---|---|
Vielen Dank für deine Antwort. Hilft mir auf jeden Fall weiter und vor allem Interessant.
Der von dir gepostete Code läuft bei mir im übrigen mit 25 bis maximal 35 FPS. Das liegt daran, dass die Scanline nicht korrekt erfasst wird und dann immer gerne mal ein ganzes Frame darauf gewartet wird bis es weiter gehen kann. Ein schwieriges Thema welches mir nun zeigt, dass man die Finger von Optimierungen lassen sollte. Ich nutze ein UHD-Bildschirm. Die Variable scanline_max erhält bei mir den Wert 2159 maximal. Vielleicht ein Grund der nicht beachtet wurde? Denn ein FullHD-Fenster befindet sich mittig im Schirm und nimmt gerade mal 1/4 des Bildschirmes ein. Die Scanline bezieht sich aber auf den Gesamten Bildschirm! Ein Problem, dass durchaus beachtet werden muss. Deine Forever-Schleife ist ähnlich wie VWait ![]() Bevor einige jetzt meinen "Blitz3D ist ja eh nur kacke". Das Problem mit der Bildschirmsynchronisation gibt es mit jeder Sprache und jede hat seine eigen gute und schlechtere Lösungsansätze dafür. Allerdings bin ich für Verbesserungen immer offen, da mich genau diese stümperhafte Ästhetik bei der Grafikausgabe immer nervt, die den Grafikkarten- und Bildschirmherstellern anscheine egal ist. Würde mal einer auf der Welt bei der Entwicklung einer Hardware seinen Kopf einschalten, gäbe es so manche bescheuerte Ergebnisse nicht. ![]() Hatte gemeint, dass mein Codebeispiel alle Eventualitäten abdeckt. Leider ist es anscheinend nicht so. Daher mein Tipp: Verwendet CreateTimer(58) mit Flip 0, ergibt die besten Ergebnisse und ist einfach umgesetzt. |
||
Download der Draw3D2 V.1.1 für schnelle Echtzeiteffekte über Blitz3D |
Kruemelator |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Ein sehr interessantes Thema mit dem ich mich auch schon einmal beschäftigt habe.
Das Thema ist sogar so wichtig dass Grafikkarten- und Monitorhersteller FreeSync(AMD) und GSync(Nvidia) erschaffen haben. Man kann also viel Geld ausgeben und einen spezielen Monitor kaufen um das Problem zu beseitigen. Ich kann meinen Monitor auf 59 Hertz stellen (Grafiktreiber), dies dürfte dann eigendlich ziemlich nah an 58.8 (1000/17) dran sein. Da mein Monitor sogar 144Hz kann (gehöre zu den Leuten die sich sowas gekauft haben ![]() kann ich auch 100Hz einstellen. Das dürfte dann eine Ungenauigkeit von 0.000 sein! (bei 10ms oder 100Fps) Zu einer Lösungsidee: Warum nicht VWait oder Flip nutzen aber irgendwie mit WaitTimer arbeiten dass man zwar 100% Auslastung hat aber nur kurz. Also grob mit Waittimer an das Frameende rantasten/"ranwarten" (hierbei keine 100% Auslastung) und den letzten Teil mit VWait oder Flip machen (100% Auslastung). Oder mit einer Dll einen Timer nutzen der genauer ist. |
||
![]() |
Jan_Ehemaliger Admin |
![]() Antworten mit Zitat ![]() |
---|---|---|
Kennt ihr den Link:
https://www.blitzforum.de/foru...mp;start=0 ??? https://www.blitzforum.de/foru...2520#82520 |
||
between angels and insects |
![]() |
hecticSieger des IS Talentwettbewerb 2006 |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hi Jan_, den Link kannte ich nicht, brachte aber bei mir auch keine Besserung. Egal welches Beispiel ist verwendete. Ich frage mich auch, warum mein Desktop angeblich mit 180 FPS läuft, der Monitor aber nur 60 anzeigen kann. Hmmm. Eine weitere Konstante, die zur Asynchronität führt.
Hi Kruemelator, letztendlich zeigt es doch nur, dass es kein so einfaches Thema ist, wenn erst jetzt die passenden Technologien entwickelt wurden. Mein Monitor kann zwischen 56 und 75 FPS anzeigen. Aber in 3840x2160 nur in 60 FPS. Eben mal nachgeschaut. Wäre aber ein interessanter Ansatz gewesen. VWait wie auch Flip 1 gilt es zu vermeiden, da diese eine hohe Auslastung erfordern. In allen mir bekannten Prorammiersprachen übrigens. Das gleiche gilt mit Delay, wobei dieser doch zu ungenau ist. WaitTimer ist eine gute Lösung die keine Auslastung erfordert, aber ganz andere Probleme mit sich bringt. Denn dieser arbeitet anders, als man es zunähst erwarten würde. Meine Versuche gingen in unterschiedlichste Richtungen, aber am Ende ergibt der oben gepostete Code bei mir ein nahezu einwandfreies Ergebnis, da die Korrektur analog zur ScanLine erfolgt und nicht so sehr vom Zeitpunkt (welcher schwer zu ermitteln ist) abhängt. Bevor es eine selbst probiert, VWait oder Flip 1 verursachen gleiche Prozessorauslastung als würde man folgendes machen: Code: [AUSKLAPPEN] Repeat
save_old=save_new save_new=ScanLine() Until save_old>save_new Flip 0 Auch eine Annäherung per Delay bringt keine Besserung. Bleibt also nur noch der Kauf entsprechender Hardware. Experimente sollte man wohl lassen oder nur als Option in ein Spiel einbinden. |
||
Download der Draw3D2 V.1.1 für schnelle Echtzeiteffekte über Blitz3D |
![]() |
Silver_Knee |
![]() Antworten mit Zitat ![]() |
---|---|---|
Kann man in B3D eventuell Tripple-Buffering nachimplementieren? Eigentlich brauch man dafür threads denke ich...
Code: [AUSKLAPPEN] ...
Global drawBuffer=CreateImage(GraphicsWidth(),GraphicsHeight()) SetBuffer ImageBuffer(drawBuffer) Repeat Rect 100,100,10,10 ;Thread emulieren, quasi cooprative multitasking FlipMaybe Rect 10,10,10,10 FlipMaybe Oval 50,50,20,20 FlipMaybe DrawToBackBuffer() Forever Function FlipMaybe() If ScanLine()>GraphicsHeight()-20 Flip 1 EndIf End Function Function DrawToBackBuffer() SetBuffer BackBuffer() DrawImage drawBuffer SetBuffer ImageBuffer(drawBuffer) Cls Besser wäre natürlich, jemand mit DX-Kenntnissen baut ne kleine userlib, die das im Treiber aktiviert. |
||
Kruemelator |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Ist langer Post, lohnt sich aber ![]() TrippleBuffering hilft nicht, da das Problem darin besteht dass man zu schnell oder zu langsam neue Frames macht. Ich habe jetzt mal etwas rum probiert und folgendes herausgefunden: Bei zwei Flip 1 Aufrufen ohne großen Zeitabstand wartet Flip 1 nicht (ebenso VWait()). ScanLine() ist für den gesamten Bildschirm und nicht nur das Fenster wie hectic schon sagte. ScanLine() kann Werte großer als die maximale Auflösungshöhe zurückgeben. Da es bei hectic nicht vorkommt nehme ich an dass es speziell an meinem Monitor liegen. Mein Monitor(1920x1080) ist ein Model welche auf einem 3D Monitor beruht, aber anstatt abwechselnd zwei unterschiedliche Bilder mit 60 Hz anzuzeigen kann er 144Hz aber dafür kein 3D mehr. Ich vermute ScanLine() wird wegen dem größeren Grafikbuffer des Monitors diese Werte (bei mir bis zu 1117 bei 1080) erreichen. Flip 1 setzt ScanLine() zurück, Flip 0 aber nicht. Bei Holzchopfs Variante verstehe ich nicht ganz wann gewartet wird und wann nicht. Ich habe jetzt selber etwas geschrieben was sehr effizient geworden ist. Meine Methode wird nur von Flip 0 + WaitTimer() geschlagen, hat aber kein Tearing und die CPU-Auslastung ist nahe zu gleich z.T. sogar identisch. Ich ermittel den Abstand zwischen aktuellem und letztem ScanLine und prüfe ob Aktuell + Differenz größer ist als Auflösungshöhe. Wenn dies der Fall ist kann ich es mir nicht erlauben nochmal zu warten, ohne dabei das neue Frame zu verpassen. (hier kann man mit einer Toleranz arbeiten, brauchte ich aber nie) Warten tue ich mit Delay(1) oder WaitTimer() mir 1000Hz Timer, habe keinen Unterschied entdeckt. Hier mal meine CPU-Auslastung (mit Tastmanager im Fenstermodus ermittelt, wüsste nicht wie im Vollbildmodus) Mit und ohne Debug keine sichtbaren Unterschiede. 22-23 Flip 1 11-13 Flip 1 und WaitTimer() 58Hz 15-18 Flip 1 und WaitTimer() 60Hz 1-2 Flip 0 und WaitTimer() aber mit Tearing 2-3 Flip 1 annähern Ich würde jetzt mal behaupten das ist nahezu perfekt ![]() Wenn jemand möchte kann er auch eine Codearchiv Version erstellen. BlitzBasic: [AUSKLAPPEN] xfenster = 800 |
||
![]() |
hecticSieger des IS Talentwettbewerb 2006 |
![]() Antworten mit Zitat ![]() |
---|---|---|
Lange Posts sind kein Problem. Meine letzte Fassung war auch so lang, bis ich dann alles abgekürzt hatte.
Deine Variante hat bei mir durchaus eine hohe Auslastung. Diese liegt bei etwa 80% eines Prozessor Kernes. Mehr Auslastung kann Blitz3D kaum noch generieren. Mit gehaltener Leertaste sind es dann immer noch etwa 60%. Prüfe mal, ob dein Grafiktreiber überhaupt VSync akzeptiert. Denn die Treiber können durchaus solche Programmeinstellungen einfach ignorieren. Bei meiner alten ATI war es beispielsweise standardmäßig vorgegeben und musste erst manuell deaktiviert werden. Mit gedrückter Leertaste habe ich kaum Tearing feststellen können. Vielleicht einmal auf 5 Sekunden. Das ist äußerst akzeptabel, nicht aber die Auslastung. Zur Info, du kannst Tearing hauptsächlich mit horizontal bewegten Objekten feststellen. Habe dann weiter experimentiert und bin zu keiner zufriedenen Lösung gekommen. Scheint, als gäbe es hier keine software basierte Möglichkeit. Hmmm. |
||
Download der Draw3D2 V.1.1 für schnelle Echtzeiteffekte über Blitz3D |
Kruemelator |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Hast du denn auch den Auflösungswert angepasst? Aus deinen Posts würde ich entnehmen das du eine Ultra-Hd Monitor hast mit 3840x2160.
Bei dir müsste die Variable am Anfang: aktuellemonitoraufloesungY = 2160 sein und nicht 1080 wie bei mir (habe 1920x1080). Wenn du nicht veränderst wartet das Programm schon bei ScanLine() > 1080 mit Flip 1 auf das nächste Frame (also hohe CPU Auslastung). Ich hätte das im vorherigen Post deutlicher machen müssen. Bei mir funktioniert es, von 23% Auslastung (da 4-Kern ist also ein Kern voll ausgelastet) mit nur Flip 1, zu 2-3% Auslastung bei Leertaste, das ist eine Verbesserung um den Faktor 7,5-11,5. Vsync funktioniert bei mir, Tearing gibt es nur wenn ich Flip 0 nutze. Ich habe mal einen senkrechten Balken hinzugefügt. Tearing ist deutlich zu sehen wenn man die Taste 2 gedrückt hält. Die Miniruckler, wegen dem ungenauen Waittimer(), sieht man wenn man die Taste 1 gedrückt hält. Ohne Taste sorgt das Flip 1 für volle Auslastung, aber keine Miniruckler und kein Tearing. Mit Leertaste sieht es genauso wie mit nur Flip 1 aus, aber brauch nur einen Bruchteil an Leistung. Vielleicht können auch andere mal testen. BlitzBasic: [AUSKLAPPEN] xfenster = 800 |
||
![]() |
Abrexxes |
![]() Antworten mit Zitat ![]() |
---|---|---|
Anmerkung: Diese Problem wird es unter BlitzNG* nicht mehr geben. Sowohl die Timer wie auch die interne Synchronisations Probleme werden nicht mehr von Marks Quellcode, sondern von der SDL intern gesteuert.
Die Verzögerungen die zu einer "unperfekten" Sync führen rühren daher das es im originalen Code ein durchlaufender Prozess ist wobei es keine direkte Prioritäten gibt. Die SDL hingegen ist ein eigenständiger Prozess, der sowohl die Prioritäten wie auch die Sync direkt anpasst (default). Kommt die Grafikdarstellung mit der Geschwindigkeit nicht mit, wird der BlitzCore ausgebremst, beim originalen Code ist es genau andersrum, System bedingt. cu * Wenn es dann erscheint. ^^ |
||
![]() |
hecticSieger des IS Talentwettbewerb 2006 |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hi Kruemelator, hatte es tatsächlich nicht eingestellt gehabt. Stelle ich es ein, bessert sich die Sache erheblich. Es zukelt gelegentlich, was nicht mehr so schlimm ist. Prozessorauslastung ist wunderbar. Allerdings läuft meine Variante im Ausgangspost auf meinem Bildschirm weiterhin besser. Es sind hier tatsächlich zu viele Faktoren, die man schlecht beeinflussen oder optimieren kann.
Hi Abrexxes, schön zu hören. Macht mich alles umso neugieriger das ganze und ich arbeite mal an meinen Editoren und der Ultimate weiter. Heute ist Zeit dafür. |
||
Download der Draw3D2 V.1.1 für schnelle Echtzeiteffekte über Blitz3D |
![]() |
TimBo |
![]() Antworten mit Zitat ![]() |
---|---|---|
wenn waittimer das gefundene Problem warum nicht einfach einen akurateren implementieren? | ||
mfg Tim Borowski // CPU: Ryzen 2700x GPU: Nvidia RTX 2070 OC (Gigabyte) Ram: 16GB DDR4 @ 3000MHz OS: Windows 10
Stolzer Gewinner des BCC 25 & BCC 31 hat einen ersten Preis in der 1. Runde beim BWInf 2010/2011 & 2011/12 mit BlitzBasic erreicht. |
![]() |
hecticSieger des IS Talentwettbewerb 2006 |
![]() Antworten mit Zitat ![]() |
---|---|---|
Das Problem ist überschaubar. Es ist zwar kein Weltuntergang, ginge aber auch besser. Dafür extra eine DLL zu laden fände ich etwas übertrieben. Ich hatte gehofft es allein mit Blitz-Bortmitteln lösen zu können. Und sofern BlitzNG das besser macht, hoffe ich auf diese Lösung. Bis dahin verbleibe ich mit einem fixierten Timer auf 58 FPS. Alles andere ist mir aktuell zu experimentell, wie die ganzen unterschiedliche Ergebnisse zeigten. | ||
Download der Draw3D2 V.1.1 für schnelle Echtzeiteffekte über Blitz3D |
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group